From 50b48aec6ddd451a6d1709c0942477b503457663 Mon Sep 17 00:00:00 2001 From: tpearson Date: Wed, 3 Feb 2010 02:15:56 +0000 Subject: Added abandoned KDE3 version of K3B git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/k3b@1084400 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- libk3b/Makefile.am | 28 + libk3b/README | 29 + libk3b/cddb/Makefile.am | 9 + libk3b/cddb/k3bcddb.cpp | 280 + libk3b/cddb/k3bcddb.h | 103 + libk3b/cddb/k3bcddbhttpquery.cpp | 233 + libk3b/cddb/k3bcddbhttpquery.h | 64 + libk3b/cddb/k3bcddblocalquery.cpp | 129 + libk3b/cddb/k3bcddblocalquery.h | 48 + libk3b/cddb/k3bcddblocalsubmit.cpp | 102 + libk3b/cddb/k3bcddblocalsubmit.h | 43 + libk3b/cddb/k3bcddbmultientriesdialog.cpp | 74 + libk3b/cddb/k3bcddbmultientriesdialog.h | 48 + libk3b/cddb/k3bcddbpquery.cpp | 278 + libk3b/cddb/k3bcddbpquery.h | 62 + libk3b/cddb/k3bcddbquery.cpp | 275 + libk3b/cddb/k3bcddbquery.h | 115 + libk3b/cddb/k3bcddbresult.cpp | 49 + libk3b/cddb/k3bcddbresult.h | 79 + libk3b/cddb/k3bcddbsubmit.cpp | 84 + libk3b/cddb/k3bcddbsubmit.h | 60 + libk3b/configure.in.in | 3 + libk3b/core/Makefile.am | 19 + libk3b/core/k3b_export.h | 33 + libk3b/core/k3bcore.cpp | 375 + libk3b/core/k3bcore.h | 181 + libk3b/core/k3bdataevent.h | 48 + libk3b/core/k3bdefaultexternalprograms.cpp | 1030 ++ libk3b/core/k3bdefaultexternalprograms.h | 143 + libk3b/core/k3bexternalbinmanager.cpp | 389 + libk3b/core/k3bexternalbinmanager.h | 162 + libk3b/core/k3bglobals.cpp | 634 + libk3b/core/k3bglobals.h | 257 + libk3b/core/k3bglobalsettings.cpp | 61 + libk3b/core/k3bglobalsettings.h | 70 + libk3b/core/k3bjob.cpp | 253 + libk3b/core/k3bjob.h | 311 + libk3b/core/k3bjobhandler.h | 64 + libk3b/core/k3bprocess.cpp | 452 + libk3b/core/k3bprocess.h | 204 + libk3b/core/k3bprogressinfoevent.h | 85 + libk3b/core/k3bsimplejobhandler.cpp | 62 + libk3b/core/k3bsimplejobhandler.h | 61 + libk3b/core/k3bthread.cpp | 221 + libk3b/core/k3bthread.h | 95 + libk3b/core/k3bthreadjob.cpp | 161 + libk3b/core/k3bthreadjob.h | 89 + libk3b/core/k3bversion.cpp | 318 + libk3b/core/k3bversion.h | 141 + libk3b/dummy.cpp | 1 + libk3b/jobs/Makefile.am | 43 + libk3b/jobs/k3baudiocuefilewritingjob.cpp | 272 + libk3b/jobs/k3baudiocuefilewritingjob.h | 79 + libk3b/jobs/k3baudiosessionreadingjob.cpp | 278 + libk3b/jobs/k3baudiosessionreadingjob.h | 75 + libk3b/jobs/k3bbinimagewritingjob.cpp | 234 + libk3b/jobs/k3bbinimagewritingjob.h | 79 + libk3b/jobs/k3bblankingjob.cpp | 176 + libk3b/jobs/k3bblankingjob.h | 71 + libk3b/jobs/k3bcdcopyjob.cpp | 1213 ++ libk3b/jobs/k3bcdcopyjob.h | 117 + libk3b/jobs/k3bcdda2wavreader.cpp | 254 + libk3b/jobs/k3bcdda2wavreader.h | 70 + libk3b/jobs/k3bclonejob.cpp | 375 + libk3b/jobs/k3bclonejob.h | 99 + libk3b/jobs/k3bclonetocreader.cpp | 235 + libk3b/jobs/k3bclonetocreader.h | 45 + libk3b/jobs/k3bdatatrackreader.cpp | 515 + libk3b/jobs/k3bdatatrackreader.h | 87 + libk3b/jobs/k3bdvdcopyjob.cpp | 894 + libk3b/jobs/k3bdvdcopyjob.h | 99 + libk3b/jobs/k3bdvdformattingjob.cpp | 536 + libk3b/jobs/k3bdvdformattingjob.h | 91 + libk3b/jobs/k3biso9660imagewritingjob.cpp | 458 + libk3b/jobs/k3biso9660imagewritingjob.h | 98 + libk3b/jobs/k3breadcdreader.cpp | 335 + libk3b/jobs/k3breadcdreader.h | 91 + libk3b/jobs/k3bverificationjob.cpp | 384 + libk3b/jobs/k3bverificationjob.h | 92 + libk3b/jobs/k3bvideodvdtitledetectclippingjob.cpp | 291 + libk3b/jobs/k3bvideodvdtitledetectclippingjob.h | 106 + libk3b/jobs/k3bvideodvdtitletranscodingjob.cpp | 583 + libk3b/jobs/k3bvideodvdtitletranscodingjob.h | 275 + libk3b/k3bimage.xsd | 175 + libk3b/plugin/Makefile.am | 28 + libk3b/plugin/k3baudioclient.cpp | 46 + libk3b/plugin/k3baudioclient.h | 51 + libk3b/plugin/k3baudiodecoder.cpp | 599 + libk3b/plugin/k3baudiodecoder.h | 254 + libk3b/plugin/k3baudioencoder.cpp | 175 + libk3b/plugin/k3baudioencoder.h | 203 + libk3b/plugin/k3baudiooutputplugin.h | 69 + libk3b/plugin/k3baudioserver.cpp | 214 + libk3b/plugin/k3baudioserver.h | 85 + libk3b/plugin/k3bplugin.cpp | 36 + libk3b/plugin/k3bplugin.h | 113 + libk3b/plugin/k3bpluginconfigwidget.cpp | 48 + libk3b/plugin/k3bpluginconfigwidget.h | 40 + libk3b/plugin/k3bpluginfactory.cpp | 33 + libk3b/plugin/k3bpluginfactory.h | 98 + libk3b/plugin/k3bpluginmanager.cpp | 189 + libk3b/plugin/k3bpluginmanager.h | 70 + libk3b/plugin/k3bprojectplugin.h | 161 + libk3b/plugin/libsamplerate/Makefile.am | 20 + libk3b/plugin/libsamplerate/common.h | 105 + libk3b/plugin/libsamplerate/configure.in.in | 13 + libk3b/plugin/libsamplerate/fastest_coeffs.h | 2493 +++ libk3b/plugin/libsamplerate/float_cast.h | 203 + libk3b/plugin/libsamplerate/high_qual_coeffs.h | 17116 +++++++++++++++++++ libk3b/plugin/libsamplerate/mid_qual_coeffs.h | 5315 ++++++ libk3b/plugin/libsamplerate/samplerate.c | 301 + libk3b/plugin/libsamplerate/samplerate.h | 138 + libk3b/plugin/libsamplerate/src_linear.c | 194 + libk3b/plugin/libsamplerate/src_sinc.c | 471 + libk3b/plugin/libsamplerate/src_zoh.c | 186 + libk3b/projects/Makefile.am | 32 + libk3b/projects/audiocd/Makefile.am | 35 + libk3b/projects/audiocd/k3baudiocdtrackdrag.cpp | 109 + libk3b/projects/audiocd/k3baudiocdtrackdrag.h | 50 + libk3b/projects/audiocd/k3baudiocdtracksource.cpp | 262 + libk3b/projects/audiocd/k3baudiocdtracksource.h | 99 + libk3b/projects/audiocd/k3baudiodatasource.cpp | 210 + libk3b/projects/audiocd/k3baudiodatasource.h | 168 + .../audiocd/k3baudiodatasourceiterator.cpp | 71 + .../projects/audiocd/k3baudiodatasourceiterator.h | 61 + libk3b/projects/audiocd/k3baudiodoc.cpp | 1127 ++ libk3b/projects/audiocd/k3baudiodoc.h | 263 + libk3b/projects/audiocd/k3baudiofile.cpp | 112 + libk3b/projects/audiocd/k3baudiofile.h | 85 + libk3b/projects/audiocd/k3baudioimager.cpp | 203 + libk3b/projects/audiocd/k3baudioimager.h | 59 + libk3b/projects/audiocd/k3baudiojob.cpp | 864 + libk3b/projects/audiocd/k3baudiojob.h | 107 + libk3b/projects/audiocd/k3baudiojobtempdata.cpp | 132 + libk3b/projects/audiocd/k3baudiojobtempdata.h | 64 + libk3b/projects/audiocd/k3baudiomaxspeedjob.cpp | 224 + libk3b/projects/audiocd/k3baudiomaxspeedjob.h | 43 + libk3b/projects/audiocd/k3baudionormalizejob.cpp | 205 + libk3b/projects/audiocd/k3baudionormalizejob.h | 63 + libk3b/projects/audiocd/k3baudiotrack.cpp | 628 + libk3b/projects/audiocd/k3baudiotrack.h | 214 + libk3b/projects/audiocd/k3baudiozerodata.cpp | 115 + libk3b/projects/audiocd/k3baudiozerodata.h | 55 + libk3b/projects/datacd/Makefile.am | 35 + libk3b/projects/datacd/k3bbootitem.cpp | 58 + libk3b/projects/datacd/k3bbootitem.h | 66 + libk3b/projects/datacd/k3bdatadoc.cpp | 1376 ++ libk3b/projects/datacd/k3bdatadoc.h | 297 + libk3b/projects/datacd/k3bdataitem.cpp | 264 + libk3b/projects/datacd/k3bdataitem.h | 225 + libk3b/projects/datacd/k3bdatajob.cpp | 972 ++ libk3b/projects/datacd/k3bdatajob.h | 111 + libk3b/projects/datacd/k3bdatapreparationjob.cpp | 283 + libk3b/projects/datacd/k3bdatapreparationjob.h | 51 + libk3b/projects/datacd/k3bdiritem.cpp | 406 + libk3b/projects/datacd/k3bdiritem.h | 155 + .../datacd/k3bfilecompilationsizehandler.cpp | 228 + .../datacd/k3bfilecompilationsizehandler.h | 73 + libk3b/projects/datacd/k3bfileitem.cpp | 300 + libk3b/projects/datacd/k3bfileitem.h | 124 + libk3b/projects/datacd/k3bisoimager.cpp | 1187 ++ libk3b/projects/datacd/k3bisoimager.h | 188 + libk3b/projects/datacd/k3bisooptions.cpp | 216 + libk3b/projects/datacd/k3bisooptions.h | 183 + libk3b/projects/datacd/k3bmkisofshandler.cpp | 150 + libk3b/projects/datacd/k3bmkisofshandler.h | 74 + libk3b/projects/datacd/k3bmsinfofetcher.cpp | 243 + libk3b/projects/datacd/k3bmsinfofetcher.h | 64 + libk3b/projects/datacd/k3bsessionimportitem.cpp | 59 + libk3b/projects/datacd/k3bsessionimportitem.h | 63 + libk3b/projects/datacd/k3bspecialdataitem.h | 76 + libk3b/projects/datadvd/Makefile.am | 21 + libk3b/projects/datadvd/k3bdvdbooktypejob.cpp | 350 + libk3b/projects/datadvd/k3bdvdbooktypejob.h | 99 + libk3b/projects/datadvd/k3bdvddoc.cpp | 39 + libk3b/projects/datadvd/k3bdvddoc.h | 37 + libk3b/projects/datadvd/k3bdvdjob.cpp | 344 + libk3b/projects/datadvd/k3bdvdjob.h | 57 + libk3b/projects/datadvd/k3bdvdview.cpp | 48 + libk3b/projects/datadvd/k3bdvdview.h | 40 + libk3b/projects/k3babstractwriter.cpp | 96 + libk3b/projects/k3babstractwriter.h | 92 + libk3b/projects/k3bcdrdaowriter.cpp | 1101 ++ libk3b/projects/k3bcdrdaowriter.h | 157 + libk3b/projects/k3bcdrecordwriter.cpp | 810 + libk3b/projects/k3bcdrecordwriter.h | 123 + libk3b/projects/k3bcuefileparser.cpp | 461 + libk3b/projects/k3bcuefileparser.h | 57 + libk3b/projects/k3bdoc.cpp | 221 + libk3b/projects/k3bdoc.h | 229 + libk3b/projects/k3bdvdrecordwriter.cpp | 119 + libk3b/projects/k3bdvdrecordwriter.h | 40 + libk3b/projects/k3bgrowisofshandler.cpp | 318 + libk3b/projects/k3bgrowisofshandler.h | 87 + libk3b/projects/k3bgrowisofswriter.cpp | 630 + libk3b/projects/k3bgrowisofswriter.h | 106 + libk3b/projects/k3bimagefilereader.cpp | 88 + libk3b/projects/k3bimagefilereader.h | 55 + libk3b/projects/k3binffilewriter.cpp | 186 + libk3b/projects/k3binffilewriter.h | 119 + libk3b/projects/k3bpipebuffer.cpp | 281 + libk3b/projects/k3bpipebuffer.h | 59 + libk3b/projects/k3btocfilewriter.cpp | 356 + libk3b/projects/k3btocfilewriter.h | 62 + libk3b/projects/mixedcd/Makefile.am | 23 + libk3b/projects/mixedcd/k3bmixeddoc.cpp | 249 + libk3b/projects/mixedcd/k3bmixeddoc.h | 95 + libk3b/projects/mixedcd/k3bmixedjob.cpp | 1339 ++ libk3b/projects/mixedcd/k3bmixedjob.h | 144 + libk3b/projects/movixcd/Makefile.am | 23 + libk3b/projects/movixcd/k3bmovixdoc.cpp | 445 + libk3b/projects/movixcd/k3bmovixdoc.h | 125 + libk3b/projects/movixcd/k3bmovixdocpreparer.cpp | 490 + libk3b/projects/movixcd/k3bmovixdocpreparer.h | 67 + libk3b/projects/movixcd/k3bmovixfileitem.cpp | 68 + libk3b/projects/movixcd/k3bmovixfileitem.h | 52 + libk3b/projects/movixcd/k3bmovixjob.cpp | 132 + libk3b/projects/movixcd/k3bmovixjob.h | 60 + libk3b/projects/movixcd/k3bmovixprogram.cpp | 339 + libk3b/projects/movixcd/k3bmovixprogram.h | 103 + libk3b/projects/movixdvd/Makefile.am | 21 + libk3b/projects/movixdvd/k3bmovixdvddoc.cpp | 36 + libk3b/projects/movixdvd/k3bmovixdvddoc.h | 40 + libk3b/projects/movixdvd/k3bmovixdvdjob.cpp | 131 + libk3b/projects/movixdvd/k3bmovixdvdjob.h | 60 + libk3b/projects/videocd/Makefile.am | 20 + libk3b/projects/videocd/cdi/Makefile.am | 5 + libk3b/projects/videocd/cdi/cdi_imag.rtf | Bin 0 -> 1314877 bytes libk3b/projects/videocd/cdi/cdi_text.fnt | Bin 0 -> 13616 bytes libk3b/projects/videocd/cdi/cdi_vcd.app | Bin 0 -> 102400 bytes libk3b/projects/videocd/cdi/cdi_vcd.cfg | 12 + libk3b/projects/videocd/cdi/icdia.htm | 12 + libk3b/projects/videocd/cdi/vcd_on_cdi_41.pdf | Bin 0 -> 126675 bytes libk3b/projects/videocd/extra/Makefile.am | 5 + libk3b/projects/videocd/extra/k3bphotosvcd.mpg | Bin 0 -> 824970 bytes libk3b/projects/videocd/extra/k3bphotovcd.mpg | Bin 0 -> 1731138 bytes libk3b/projects/videocd/k3bvcddoc.cpp | 894 + libk3b/projects/videocd/k3bvcddoc.h | 192 + libk3b/projects/videocd/k3bvcdjob.cpp | 567 + libk3b/projects/videocd/k3bvcdjob.h | 115 + libk3b/projects/videocd/k3bvcdoptions.cpp | 146 + libk3b/projects/videocd/k3bvcdoptions.h | 377 + libk3b/projects/videocd/k3bvcdtrack.cpp | 456 + libk3b/projects/videocd/k3bvcdtrack.h | 198 + libk3b/projects/videocd/k3bvcdxmlview.cpp | 440 + libk3b/projects/videocd/k3bvcdxmlview.h | 59 + libk3b/projects/videocd/mpeginfo/Makefile.am | 5 + libk3b/projects/videocd/mpeginfo/k3bmpeginfo.cpp | 844 + libk3b/projects/videocd/mpeginfo/k3bmpeginfo.h | 178 + libk3b/projects/videodvd/Makefile.am | 20 + libk3b/projects/videodvd/k3bvideodvddoc.cpp | 71 + libk3b/projects/videodvd/k3bvideodvddoc.h | 46 + libk3b/projects/videodvd/k3bvideodvdimager.cpp | 221 + libk3b/projects/videodvd/k3bvideodvdimager.h | 61 + libk3b/projects/videodvd/k3bvideodvdjob.cpp | 101 + libk3b/projects/videodvd/k3bvideodvdjob.h | 46 + libk3b/scripts/Makefile.am | 11 + libk3b/scripts/k3b_automount | 66 + libk3b/tools/Makefile.am | 44 + libk3b/tools/k3bactivepipe.cpp | 255 + libk3b/tools/k3bactivepipe.h | 134 + libk3b/tools/k3bbusywidget.cpp | 103 + libk3b/tools/k3bbusywidget.h | 54 + libk3b/tools/k3bcdparanoialib.cpp | 783 + libk3b/tools/k3bcdparanoialib.h | 161 + libk3b/tools/k3bcdtextvalidator.cpp | 42 + libk3b/tools/k3bcdtextvalidator.h | 33 + libk3b/tools/k3bchecksumpipe.cpp | 99 + libk3b/tools/k3bchecksumpipe.h | 66 + libk3b/tools/k3bcutcombobox.cpp | 230 + libk3b/tools/k3bcutcombobox.h | 92 + libk3b/tools/k3bdevicecombobox.cpp | 174 + libk3b/tools/k3bdevicecombobox.h | 67 + libk3b/tools/k3bdevicehandler.cpp | 332 + libk3b/tools/k3bdevicehandler.h | 237 + libk3b/tools/k3bdeviceselectiondialog.cpp | 130 + libk3b/tools/k3bdeviceselectiondialog.h | 62 + libk3b/tools/k3bdirsizejob.cpp | 184 + libk3b/tools/k3bdirsizejob.h | 67 + libk3b/tools/k3bexceptions.cpp | 43 + libk3b/tools/k3bexceptions.h | 35 + libk3b/tools/k3bfilesplitter.cpp | 307 + libk3b/tools/k3bfilesplitter.h | 108 + libk3b/tools/k3bfilesysteminfo.cpp | 141 + libk3b/tools/k3bfilesysteminfo.h | 56 + libk3b/tools/k3bintmapcombobox.cpp | 127 + libk3b/tools/k3bintmapcombobox.h | 83 + libk3b/tools/k3bintvalidator.cpp | 137 + libk3b/tools/k3bintvalidator.h | 84 + libk3b/tools/k3biso9660.cpp | 899 + libk3b/tools/k3biso9660.h | 453 + libk3b/tools/k3biso9660backend.cpp | 239 + libk3b/tools/k3biso9660backend.h | 95 + libk3b/tools/k3blibdvdcss.cpp | 307 + libk3b/tools/k3blibdvdcss.h | 84 + libk3b/tools/k3blistview.cpp | 1290 ++ libk3b/tools/k3blistview.h | 296 + libk3b/tools/k3blistviewitemanimator.cpp | 137 + libk3b/tools/k3blistviewitemanimator.h | 78 + libk3b/tools/k3bmd5job.cpp | 322 + libk3b/tools/k3bmd5job.h | 92 + libk3b/tools/k3bmsfedit.cpp | 153 + libk3b/tools/k3bmsfedit.h | 70 + libk3b/tools/k3bmultichoicedialog.cpp | 191 + libk3b/tools/k3bmultichoicedialog.h | 73 + libk3b/tools/k3bpipe.cpp | 79 + libk3b/tools/k3bpipe.h | 60 + libk3b/tools/k3bprogressdialog.cpp | 107 + libk3b/tools/k3bprogressdialog.h | 63 + libk3b/tools/k3bpushbutton.cpp | 136 + libk3b/tools/k3bpushbutton.h | 75 + libk3b/tools/k3bradioaction.cpp | 94 + libk3b/tools/k3bradioaction.h | 122 + libk3b/tools/k3brichtextlabel.cpp | 109 + libk3b/tools/k3brichtextlabel.h | 62 + libk3b/tools/k3bsignalwaiter.cpp | 62 + libk3b/tools/k3bsignalwaiter.h | 51 + libk3b/tools/k3bstdguiitems.cpp | 215 + libk3b/tools/k3bstdguiitems.h | 45 + libk3b/tools/k3bstringutils.cpp | 111 + libk3b/tools/k3bstringutils.h | 39 + libk3b/tools/k3btempfile.cpp | 51 + libk3b/tools/k3btempfile.h | 43 + libk3b/tools/k3bthreadwidget.cpp | 142 + libk3b/tools/k3bthreadwidget.h | 78 + libk3b/tools/k3bthroughputestimator.cpp | 98 + libk3b/tools/k3bthroughputestimator.h | 57 + libk3b/tools/k3btitlelabel.cpp | 266 + libk3b/tools/k3btitlelabel.h | 68 + libk3b/tools/k3btoolbox.cpp | 293 + libk3b/tools/k3btoolbox.h | 93 + libk3b/tools/k3btoolbutton.cpp | 109 + libk3b/tools/k3btoolbutton.h | 50 + libk3b/tools/k3bvalidators.cpp | 154 + libk3b/tools/k3bvalidators.h | 131 + libk3b/tools/k3bwavefilewriter.cpp | 186 + libk3b/tools/k3bwavefilewriter.h | 78 + libk3b/tools/kcutlabel.cpp | 115 + libk3b/tools/kcutlabel.h | 68 + libk3b/tools/libisofs/COPYING | 280 + libk3b/tools/libisofs/ChangeLog | 9 + libk3b/tools/libisofs/Makefile.am | 5 + libk3b/tools/libisofs/README | 24 + libk3b/tools/libisofs/bswap.h | 94 + libk3b/tools/libisofs/el_torito.h | 63 + libk3b/tools/libisofs/iso_fs.h | 219 + libk3b/tools/libisofs/isofs.cpp | 878 + libk3b/tools/libisofs/isofs.h | 151 + libk3b/tools/libisofs/rock.h | 127 + libk3b/videodvd/Makefile.am | 19 + libk3b/videodvd/configure.in.bot | 11 + libk3b/videodvd/configure.in.in | 28 + libk3b/videodvd/k3bvideodvd.cpp | 327 + libk3b/videodvd/k3bvideodvd.h | 91 + libk3b/videodvd/k3bvideodvdaudiostream.h | 112 + libk3b/videodvd/k3bvideodvdptt.h | 50 + libk3b/videodvd/k3bvideodvdsubpicturestream.h | 68 + libk3b/videodvd/k3bvideodvdtime.cpp | 106 + libk3b/videodvd/k3bvideodvdtime.h | 59 + libk3b/videodvd/k3bvideodvdtitle.h | 112 + libk3b/videodvd/k3bvideodvdvideostream.cpp | 60 + libk3b/videodvd/k3bvideodvdvideostream.h | 107 + 362 files changed, 91051 insertions(+) create mode 100644 libk3b/Makefile.am create mode 100644 libk3b/README create mode 100644 libk3b/cddb/Makefile.am create mode 100644 libk3b/cddb/k3bcddb.cpp create mode 100644 libk3b/cddb/k3bcddb.h create mode 100644 libk3b/cddb/k3bcddbhttpquery.cpp create mode 100644 libk3b/cddb/k3bcddbhttpquery.h create mode 100644 libk3b/cddb/k3bcddblocalquery.cpp create mode 100644 libk3b/cddb/k3bcddblocalquery.h create mode 100644 libk3b/cddb/k3bcddblocalsubmit.cpp create mode 100644 libk3b/cddb/k3bcddblocalsubmit.h create mode 100644 libk3b/cddb/k3bcddbmultientriesdialog.cpp create mode 100644 libk3b/cddb/k3bcddbmultientriesdialog.h create mode 100644 libk3b/cddb/k3bcddbpquery.cpp create mode 100644 libk3b/cddb/k3bcddbpquery.h create mode 100644 libk3b/cddb/k3bcddbquery.cpp create mode 100644 libk3b/cddb/k3bcddbquery.h create mode 100644 libk3b/cddb/k3bcddbresult.cpp create mode 100644 libk3b/cddb/k3bcddbresult.h create mode 100644 libk3b/cddb/k3bcddbsubmit.cpp create mode 100644 libk3b/cddb/k3bcddbsubmit.h create mode 100644 libk3b/configure.in.in create mode 100644 libk3b/core/Makefile.am create mode 100644 libk3b/core/k3b_export.h create mode 100644 libk3b/core/k3bcore.cpp create mode 100644 libk3b/core/k3bcore.h create mode 100644 libk3b/core/k3bdataevent.h create mode 100644 libk3b/core/k3bdefaultexternalprograms.cpp create mode 100644 libk3b/core/k3bdefaultexternalprograms.h create mode 100644 libk3b/core/k3bexternalbinmanager.cpp create mode 100644 libk3b/core/k3bexternalbinmanager.h create mode 100644 libk3b/core/k3bglobals.cpp create mode 100644 libk3b/core/k3bglobals.h create mode 100644 libk3b/core/k3bglobalsettings.cpp create mode 100644 libk3b/core/k3bglobalsettings.h create mode 100644 libk3b/core/k3bjob.cpp create mode 100644 libk3b/core/k3bjob.h create mode 100644 libk3b/core/k3bjobhandler.h create mode 100644 libk3b/core/k3bprocess.cpp create mode 100644 libk3b/core/k3bprocess.h create mode 100644 libk3b/core/k3bprogressinfoevent.h create mode 100644 libk3b/core/k3bsimplejobhandler.cpp create mode 100644 libk3b/core/k3bsimplejobhandler.h create mode 100644 libk3b/core/k3bthread.cpp create mode 100644 libk3b/core/k3bthread.h create mode 100644 libk3b/core/k3bthreadjob.cpp create mode 100644 libk3b/core/k3bthreadjob.h create mode 100644 libk3b/core/k3bversion.cpp create mode 100644 libk3b/core/k3bversion.h create mode 100644 libk3b/dummy.cpp create mode 100644 libk3b/jobs/Makefile.am create mode 100644 libk3b/jobs/k3baudiocuefilewritingjob.cpp create mode 100644 libk3b/jobs/k3baudiocuefilewritingjob.h create mode 100644 libk3b/jobs/k3baudiosessionreadingjob.cpp create mode 100644 libk3b/jobs/k3baudiosessionreadingjob.h create mode 100644 libk3b/jobs/k3bbinimagewritingjob.cpp create mode 100644 libk3b/jobs/k3bbinimagewritingjob.h create mode 100644 libk3b/jobs/k3bblankingjob.cpp create mode 100644 libk3b/jobs/k3bblankingjob.h create mode 100644 libk3b/jobs/k3bcdcopyjob.cpp create mode 100644 libk3b/jobs/k3bcdcopyjob.h create mode 100644 libk3b/jobs/k3bcdda2wavreader.cpp create mode 100644 libk3b/jobs/k3bcdda2wavreader.h create mode 100644 libk3b/jobs/k3bclonejob.cpp create mode 100644 libk3b/jobs/k3bclonejob.h create mode 100644 libk3b/jobs/k3bclonetocreader.cpp create mode 100644 libk3b/jobs/k3bclonetocreader.h create mode 100644 libk3b/jobs/k3bdatatrackreader.cpp create mode 100644 libk3b/jobs/k3bdatatrackreader.h create mode 100644 libk3b/jobs/k3bdvdcopyjob.cpp create mode 100644 libk3b/jobs/k3bdvdcopyjob.h create mode 100644 libk3b/jobs/k3bdvdformattingjob.cpp create mode 100644 libk3b/jobs/k3bdvdformattingjob.h create mode 100644 libk3b/jobs/k3biso9660imagewritingjob.cpp create mode 100644 libk3b/jobs/k3biso9660imagewritingjob.h create mode 100644 libk3b/jobs/k3breadcdreader.cpp create mode 100644 libk3b/jobs/k3breadcdreader.h create mode 100644 libk3b/jobs/k3bverificationjob.cpp create mode 100644 libk3b/jobs/k3bverificationjob.h create mode 100644 libk3b/jobs/k3bvideodvdtitledetectclippingjob.cpp create mode 100644 libk3b/jobs/k3bvideodvdtitledetectclippingjob.h create mode 100644 libk3b/jobs/k3bvideodvdtitletranscodingjob.cpp create mode 100644 libk3b/jobs/k3bvideodvdtitletranscodingjob.h create mode 100644 libk3b/k3bimage.xsd create mode 100644 libk3b/plugin/Makefile.am create mode 100644 libk3b/plugin/k3baudioclient.cpp create mode 100644 libk3b/plugin/k3baudioclient.h create mode 100644 libk3b/plugin/k3baudiodecoder.cpp create mode 100644 libk3b/plugin/k3baudiodecoder.h create mode 100644 libk3b/plugin/k3baudioencoder.cpp create mode 100644 libk3b/plugin/k3baudioencoder.h create mode 100644 libk3b/plugin/k3baudiooutputplugin.h create mode 100644 libk3b/plugin/k3baudioserver.cpp create mode 100644 libk3b/plugin/k3baudioserver.h create mode 100644 libk3b/plugin/k3bplugin.cpp create mode 100644 libk3b/plugin/k3bplugin.h create mode 100644 libk3b/plugin/k3bpluginconfigwidget.cpp create mode 100644 libk3b/plugin/k3bpluginconfigwidget.h create mode 100644 libk3b/plugin/k3bpluginfactory.cpp create mode 100644 libk3b/plugin/k3bpluginfactory.h create mode 100644 libk3b/plugin/k3bpluginmanager.cpp create mode 100644 libk3b/plugin/k3bpluginmanager.h create mode 100644 libk3b/plugin/k3bprojectplugin.h create mode 100644 libk3b/plugin/libsamplerate/Makefile.am create mode 100644 libk3b/plugin/libsamplerate/common.h create mode 100644 libk3b/plugin/libsamplerate/configure.in.in create mode 100644 libk3b/plugin/libsamplerate/fastest_coeffs.h create mode 100644 libk3b/plugin/libsamplerate/float_cast.h create mode 100644 libk3b/plugin/libsamplerate/high_qual_coeffs.h create mode 100644 libk3b/plugin/libsamplerate/mid_qual_coeffs.h create mode 100644 libk3b/plugin/libsamplerate/samplerate.c create mode 100644 libk3b/plugin/libsamplerate/samplerate.h create mode 100644 libk3b/plugin/libsamplerate/src_linear.c create mode 100644 libk3b/plugin/libsamplerate/src_sinc.c create mode 100644 libk3b/plugin/libsamplerate/src_zoh.c create mode 100644 libk3b/projects/Makefile.am create mode 100644 libk3b/projects/audiocd/Makefile.am create mode 100644 libk3b/projects/audiocd/k3baudiocdtrackdrag.cpp create mode 100644 libk3b/projects/audiocd/k3baudiocdtrackdrag.h create mode 100644 libk3b/projects/audiocd/k3baudiocdtracksource.cpp create mode 100644 libk3b/projects/audiocd/k3baudiocdtracksource.h create mode 100644 libk3b/projects/audiocd/k3baudiodatasource.cpp create mode 100644 libk3b/projects/audiocd/k3baudiodatasource.h create mode 100644 libk3b/projects/audiocd/k3baudiodatasourceiterator.cpp create mode 100644 libk3b/projects/audiocd/k3baudiodatasourceiterator.h create mode 100644 libk3b/projects/audiocd/k3baudiodoc.cpp create mode 100644 libk3b/projects/audiocd/k3baudiodoc.h create mode 100644 libk3b/projects/audiocd/k3baudiofile.cpp create mode 100644 libk3b/projects/audiocd/k3baudiofile.h create mode 100644 libk3b/projects/audiocd/k3baudioimager.cpp create mode 100644 libk3b/projects/audiocd/k3baudioimager.h create mode 100644 libk3b/projects/audiocd/k3baudiojob.cpp create mode 100644 libk3b/projects/audiocd/k3baudiojob.h create mode 100644 libk3b/projects/audiocd/k3baudiojobtempdata.cpp create mode 100644 libk3b/projects/audiocd/k3baudiojobtempdata.h create mode 100644 libk3b/projects/audiocd/k3baudiomaxspeedjob.cpp create mode 100644 libk3b/projects/audiocd/k3baudiomaxspeedjob.h create mode 100644 libk3b/projects/audiocd/k3baudionormalizejob.cpp create mode 100644 libk3b/projects/audiocd/k3baudionormalizejob.h create mode 100644 libk3b/projects/audiocd/k3baudiotrack.cpp create mode 100644 libk3b/projects/audiocd/k3baudiotrack.h create mode 100644 libk3b/projects/audiocd/k3baudiozerodata.cpp create mode 100644 libk3b/projects/audiocd/k3baudiozerodata.h create mode 100644 libk3b/projects/datacd/Makefile.am create mode 100644 libk3b/projects/datacd/k3bbootitem.cpp create mode 100644 libk3b/projects/datacd/k3bbootitem.h create mode 100644 libk3b/projects/datacd/k3bdatadoc.cpp create mode 100644 libk3b/projects/datacd/k3bdatadoc.h create mode 100644 libk3b/projects/datacd/k3bdataitem.cpp create mode 100644 libk3b/projects/datacd/k3bdataitem.h create mode 100644 libk3b/projects/datacd/k3bdatajob.cpp create mode 100644 libk3b/projects/datacd/k3bdatajob.h create mode 100644 libk3b/projects/datacd/k3bdatapreparationjob.cpp create mode 100644 libk3b/projects/datacd/k3bdatapreparationjob.h create mode 100644 libk3b/projects/datacd/k3bdiritem.cpp create mode 100644 libk3b/projects/datacd/k3bdiritem.h create mode 100644 libk3b/projects/datacd/k3bfilecompilationsizehandler.cpp create mode 100644 libk3b/projects/datacd/k3bfilecompilationsizehandler.h create mode 100644 libk3b/projects/datacd/k3bfileitem.cpp create mode 100644 libk3b/projects/datacd/k3bfileitem.h create mode 100644 libk3b/projects/datacd/k3bisoimager.cpp create mode 100644 libk3b/projects/datacd/k3bisoimager.h create mode 100644 libk3b/projects/datacd/k3bisooptions.cpp create mode 100644 libk3b/projects/datacd/k3bisooptions.h create mode 100644 libk3b/projects/datacd/k3bmkisofshandler.cpp create mode 100644 libk3b/projects/datacd/k3bmkisofshandler.h create mode 100644 libk3b/projects/datacd/k3bmsinfofetcher.cpp create mode 100644 libk3b/projects/datacd/k3bmsinfofetcher.h create mode 100644 libk3b/projects/datacd/k3bsessionimportitem.cpp create mode 100644 libk3b/projects/datacd/k3bsessionimportitem.h create mode 100644 libk3b/projects/datacd/k3bspecialdataitem.h create mode 100644 libk3b/projects/datadvd/Makefile.am create mode 100644 libk3b/projects/datadvd/k3bdvdbooktypejob.cpp create mode 100644 libk3b/projects/datadvd/k3bdvdbooktypejob.h create mode 100644 libk3b/projects/datadvd/k3bdvddoc.cpp create mode 100644 libk3b/projects/datadvd/k3bdvddoc.h create mode 100644 libk3b/projects/datadvd/k3bdvdjob.cpp create mode 100644 libk3b/projects/datadvd/k3bdvdjob.h create mode 100644 libk3b/projects/datadvd/k3bdvdview.cpp create mode 100644 libk3b/projects/datadvd/k3bdvdview.h create mode 100644 libk3b/projects/k3babstractwriter.cpp create mode 100644 libk3b/projects/k3babstractwriter.h create mode 100644 libk3b/projects/k3bcdrdaowriter.cpp create mode 100644 libk3b/projects/k3bcdrdaowriter.h create mode 100644 libk3b/projects/k3bcdrecordwriter.cpp create mode 100644 libk3b/projects/k3bcdrecordwriter.h create mode 100644 libk3b/projects/k3bcuefileparser.cpp create mode 100644 libk3b/projects/k3bcuefileparser.h create mode 100644 libk3b/projects/k3bdoc.cpp create mode 100644 libk3b/projects/k3bdoc.h create mode 100644 libk3b/projects/k3bdvdrecordwriter.cpp create mode 100644 libk3b/projects/k3bdvdrecordwriter.h create mode 100644 libk3b/projects/k3bgrowisofshandler.cpp create mode 100644 libk3b/projects/k3bgrowisofshandler.h create mode 100644 libk3b/projects/k3bgrowisofswriter.cpp create mode 100644 libk3b/projects/k3bgrowisofswriter.h create mode 100644 libk3b/projects/k3bimagefilereader.cpp create mode 100644 libk3b/projects/k3bimagefilereader.h create mode 100644 libk3b/projects/k3binffilewriter.cpp create mode 100644 libk3b/projects/k3binffilewriter.h create mode 100644 libk3b/projects/k3bpipebuffer.cpp create mode 100644 libk3b/projects/k3bpipebuffer.h create mode 100644 libk3b/projects/k3btocfilewriter.cpp create mode 100644 libk3b/projects/k3btocfilewriter.h create mode 100644 libk3b/projects/mixedcd/Makefile.am create mode 100644 libk3b/projects/mixedcd/k3bmixeddoc.cpp create mode 100644 libk3b/projects/mixedcd/k3bmixeddoc.h create mode 100644 libk3b/projects/mixedcd/k3bmixedjob.cpp create mode 100644 libk3b/projects/mixedcd/k3bmixedjob.h create mode 100644 libk3b/projects/movixcd/Makefile.am create mode 100644 libk3b/projects/movixcd/k3bmovixdoc.cpp create mode 100644 libk3b/projects/movixcd/k3bmovixdoc.h create mode 100644 libk3b/projects/movixcd/k3bmovixdocpreparer.cpp create mode 100644 libk3b/projects/movixcd/k3bmovixdocpreparer.h create mode 100644 libk3b/projects/movixcd/k3bmovixfileitem.cpp create mode 100644 libk3b/projects/movixcd/k3bmovixfileitem.h create mode 100644 libk3b/projects/movixcd/k3bmovixjob.cpp create mode 100644 libk3b/projects/movixcd/k3bmovixjob.h create mode 100644 libk3b/projects/movixcd/k3bmovixprogram.cpp create mode 100644 libk3b/projects/movixcd/k3bmovixprogram.h create mode 100644 libk3b/projects/movixdvd/Makefile.am create mode 100644 libk3b/projects/movixdvd/k3bmovixdvddoc.cpp create mode 100644 libk3b/projects/movixdvd/k3bmovixdvddoc.h create mode 100644 libk3b/projects/movixdvd/k3bmovixdvdjob.cpp create mode 100644 libk3b/projects/movixdvd/k3bmovixdvdjob.h create mode 100644 libk3b/projects/videocd/Makefile.am create mode 100644 libk3b/projects/videocd/cdi/Makefile.am create mode 100644 libk3b/projects/videocd/cdi/cdi_imag.rtf create mode 100644 libk3b/projects/videocd/cdi/cdi_text.fnt create mode 100644 libk3b/projects/videocd/cdi/cdi_vcd.app create mode 100644 libk3b/projects/videocd/cdi/cdi_vcd.cfg create mode 100644 libk3b/projects/videocd/cdi/icdia.htm create mode 100644 libk3b/projects/videocd/cdi/vcd_on_cdi_41.pdf create mode 100644 libk3b/projects/videocd/extra/Makefile.am create mode 100644 libk3b/projects/videocd/extra/k3bphotosvcd.mpg create mode 100644 libk3b/projects/videocd/extra/k3bphotovcd.mpg create mode 100644 libk3b/projects/videocd/k3bvcddoc.cpp create mode 100644 libk3b/projects/videocd/k3bvcddoc.h create mode 100644 libk3b/projects/videocd/k3bvcdjob.cpp create mode 100644 libk3b/projects/videocd/k3bvcdjob.h create mode 100644 libk3b/projects/videocd/k3bvcdoptions.cpp create mode 100644 libk3b/projects/videocd/k3bvcdoptions.h create mode 100644 libk3b/projects/videocd/k3bvcdtrack.cpp create mode 100644 libk3b/projects/videocd/k3bvcdtrack.h create mode 100644 libk3b/projects/videocd/k3bvcdxmlview.cpp create mode 100644 libk3b/projects/videocd/k3bvcdxmlview.h create mode 100644 libk3b/projects/videocd/mpeginfo/Makefile.am create mode 100644 libk3b/projects/videocd/mpeginfo/k3bmpeginfo.cpp create mode 100644 libk3b/projects/videocd/mpeginfo/k3bmpeginfo.h create mode 100644 libk3b/projects/videodvd/Makefile.am create mode 100644 libk3b/projects/videodvd/k3bvideodvddoc.cpp create mode 100644 libk3b/projects/videodvd/k3bvideodvddoc.h create mode 100644 libk3b/projects/videodvd/k3bvideodvdimager.cpp create mode 100644 libk3b/projects/videodvd/k3bvideodvdimager.h create mode 100644 libk3b/projects/videodvd/k3bvideodvdjob.cpp create mode 100644 libk3b/projects/videodvd/k3bvideodvdjob.h create mode 100644 libk3b/scripts/Makefile.am create mode 100755 libk3b/scripts/k3b_automount create mode 100644 libk3b/tools/Makefile.am create mode 100644 libk3b/tools/k3bactivepipe.cpp create mode 100644 libk3b/tools/k3bactivepipe.h create mode 100644 libk3b/tools/k3bbusywidget.cpp create mode 100644 libk3b/tools/k3bbusywidget.h create mode 100644 libk3b/tools/k3bcdparanoialib.cpp create mode 100644 libk3b/tools/k3bcdparanoialib.h create mode 100644 libk3b/tools/k3bcdtextvalidator.cpp create mode 100644 libk3b/tools/k3bcdtextvalidator.h create mode 100644 libk3b/tools/k3bchecksumpipe.cpp create mode 100644 libk3b/tools/k3bchecksumpipe.h create mode 100644 libk3b/tools/k3bcutcombobox.cpp create mode 100644 libk3b/tools/k3bcutcombobox.h create mode 100644 libk3b/tools/k3bdevicecombobox.cpp create mode 100644 libk3b/tools/k3bdevicecombobox.h create mode 100644 libk3b/tools/k3bdevicehandler.cpp create mode 100644 libk3b/tools/k3bdevicehandler.h create mode 100644 libk3b/tools/k3bdeviceselectiondialog.cpp create mode 100644 libk3b/tools/k3bdeviceselectiondialog.h create mode 100644 libk3b/tools/k3bdirsizejob.cpp create mode 100644 libk3b/tools/k3bdirsizejob.h create mode 100644 libk3b/tools/k3bexceptions.cpp create mode 100644 libk3b/tools/k3bexceptions.h create mode 100644 libk3b/tools/k3bfilesplitter.cpp create mode 100644 libk3b/tools/k3bfilesplitter.h create mode 100644 libk3b/tools/k3bfilesysteminfo.cpp create mode 100644 libk3b/tools/k3bfilesysteminfo.h create mode 100644 libk3b/tools/k3bintmapcombobox.cpp create mode 100644 libk3b/tools/k3bintmapcombobox.h create mode 100644 libk3b/tools/k3bintvalidator.cpp create mode 100644 libk3b/tools/k3bintvalidator.h create mode 100644 libk3b/tools/k3biso9660.cpp create mode 100644 libk3b/tools/k3biso9660.h create mode 100644 libk3b/tools/k3biso9660backend.cpp create mode 100644 libk3b/tools/k3biso9660backend.h create mode 100644 libk3b/tools/k3blibdvdcss.cpp create mode 100644 libk3b/tools/k3blibdvdcss.h create mode 100644 libk3b/tools/k3blistview.cpp create mode 100644 libk3b/tools/k3blistview.h create mode 100644 libk3b/tools/k3blistviewitemanimator.cpp create mode 100644 libk3b/tools/k3blistviewitemanimator.h create mode 100644 libk3b/tools/k3bmd5job.cpp create mode 100644 libk3b/tools/k3bmd5job.h create mode 100644 libk3b/tools/k3bmsfedit.cpp create mode 100644 libk3b/tools/k3bmsfedit.h create mode 100644 libk3b/tools/k3bmultichoicedialog.cpp create mode 100644 libk3b/tools/k3bmultichoicedialog.h create mode 100644 libk3b/tools/k3bpipe.cpp create mode 100644 libk3b/tools/k3bpipe.h create mode 100644 libk3b/tools/k3bprogressdialog.cpp create mode 100644 libk3b/tools/k3bprogressdialog.h create mode 100644 libk3b/tools/k3bpushbutton.cpp create mode 100644 libk3b/tools/k3bpushbutton.h create mode 100644 libk3b/tools/k3bradioaction.cpp create mode 100644 libk3b/tools/k3bradioaction.h create mode 100644 libk3b/tools/k3brichtextlabel.cpp create mode 100644 libk3b/tools/k3brichtextlabel.h create mode 100644 libk3b/tools/k3bsignalwaiter.cpp create mode 100644 libk3b/tools/k3bsignalwaiter.h create mode 100644 libk3b/tools/k3bstdguiitems.cpp create mode 100644 libk3b/tools/k3bstdguiitems.h create mode 100644 libk3b/tools/k3bstringutils.cpp create mode 100644 libk3b/tools/k3bstringutils.h create mode 100644 libk3b/tools/k3btempfile.cpp create mode 100644 libk3b/tools/k3btempfile.h create mode 100644 libk3b/tools/k3bthreadwidget.cpp create mode 100644 libk3b/tools/k3bthreadwidget.h create mode 100644 libk3b/tools/k3bthroughputestimator.cpp create mode 100644 libk3b/tools/k3bthroughputestimator.h create mode 100644 libk3b/tools/k3btitlelabel.cpp create mode 100644 libk3b/tools/k3btitlelabel.h create mode 100644 libk3b/tools/k3btoolbox.cpp create mode 100644 libk3b/tools/k3btoolbox.h create mode 100644 libk3b/tools/k3btoolbutton.cpp create mode 100644 libk3b/tools/k3btoolbutton.h create mode 100644 libk3b/tools/k3bvalidators.cpp create mode 100644 libk3b/tools/k3bvalidators.h create mode 100644 libk3b/tools/k3bwavefilewriter.cpp create mode 100644 libk3b/tools/k3bwavefilewriter.h create mode 100644 libk3b/tools/kcutlabel.cpp create mode 100644 libk3b/tools/kcutlabel.h create mode 100644 libk3b/tools/libisofs/COPYING create mode 100644 libk3b/tools/libisofs/ChangeLog create mode 100644 libk3b/tools/libisofs/Makefile.am create mode 100644 libk3b/tools/libisofs/README create mode 100644 libk3b/tools/libisofs/bswap.h create mode 100644 libk3b/tools/libisofs/el_torito.h create mode 100644 libk3b/tools/libisofs/iso_fs.h create mode 100644 libk3b/tools/libisofs/isofs.cpp create mode 100644 libk3b/tools/libisofs/isofs.h create mode 100644 libk3b/tools/libisofs/rock.h create mode 100644 libk3b/videodvd/Makefile.am create mode 100644 libk3b/videodvd/configure.in.bot create mode 100644 libk3b/videodvd/configure.in.in create mode 100644 libk3b/videodvd/k3bvideodvd.cpp create mode 100644 libk3b/videodvd/k3bvideodvd.h create mode 100644 libk3b/videodvd/k3bvideodvdaudiostream.h create mode 100644 libk3b/videodvd/k3bvideodvdptt.h create mode 100644 libk3b/videodvd/k3bvideodvdsubpicturestream.h create mode 100644 libk3b/videodvd/k3bvideodvdtime.cpp create mode 100644 libk3b/videodvd/k3bvideodvdtime.h create mode 100644 libk3b/videodvd/k3bvideodvdtitle.h create mode 100644 libk3b/videodvd/k3bvideodvdvideostream.cpp create mode 100644 libk3b/videodvd/k3bvideodvdvideostream.h (limited to 'libk3b') diff --git a/libk3b/Makefile.am b/libk3b/Makefile.am new file mode 100644 index 0000000..4c74f7d --- /dev/null +++ b/libk3b/Makefile.am @@ -0,0 +1,28 @@ +if include_videodvdrip +VIDEODVDDIR = videodvd +VIDEODVDLIB = videodvd/libvideodvd.la +endif + + +lib_LTLIBRARIES = libk3b.la + +libk3b_la_SOURCES = dummy.cpp + +libk3b_la_LIBADD = core/libk3bcore.la \ + cddb/libcddb.la \ + projects/libk3bproject.la \ + plugin/libk3bplugin.la \ + tools/libk3btools.la \ + jobs/libjobs.la \ + $(VIDEODVDLIB) \ + ../libk3bdevice/libk3bdevice.la + +libk3b_la_LDFLAGS = $(all_libraries) -version-info 3:0:0 -no-undefined + +SUBDIRS = core plugin tools projects cddb jobs $(VIDEODVDDIR) + +#pkgconfigdir = $(libdir)/pkgconfig +#pkgconfig_DATA = libk3b.pc + +messages: + $(XGETTEXT) `find -name "*.cpp" -o -name "*.h"` -o $(podir)/libk3b.pot diff --git a/libk3b/README b/libk3b/README new file mode 100644 index 0000000..a1ba273 --- /dev/null +++ b/libk3b/README @@ -0,0 +1,29 @@ +libk3b +========================= + +This is the k3b library which provides a lot of CD/DVD writing classes. + +If you want to use it please be aware that the API is far from stable and +there will be no binary compatibility (or even source compatibility) before +K3b 1.0. + +But you are welcome to help fix the API and improve it whereever it is needed. + + +Usage +========================== + +Just a very basic scetch how to create an audio cd: + +1. create a k3bcore instance (this provides all the stuff that is needed by the lib) +1.1 K3bCore::init() to initialize the core. + +2. create a K3bAudioDoc object and add urls to it + +3. create a K3bJobHandler derived class (for example a widget which displays the progress) + +4. call K3bAudioDoc::newBurnJob or create a K3bAudioJob manually. + +5. modify the doc's settings. + +6. call K3bAudioJob::start() to start the burning process. diff --git a/libk3b/cddb/Makefile.am b/libk3b/cddb/Makefile.am new file mode 100644 index 0000000..e73c5ce --- /dev/null +++ b/libk3b/cddb/Makefile.am @@ -0,0 +1,9 @@ +AM_CPPFLAGS = -I$(srcdir)/../core -I$(srcdir)/../../libk3bdevice -I$(srcdir)/../../src $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libcddb.la + +libcddb_la_SOURCES = k3bcddbquery.cpp k3bcddb.cpp k3bcddbresult.cpp k3bcddbhttpquery.cpp k3bcddbpquery.cpp k3bcddblocalquery.cpp k3bcddbsubmit.cpp k3bcddblocalsubmit.cpp k3bcddbmultientriesdialog.cpp + +include_HEADERS = k3bcddb.h k3bcddbresult.h diff --git a/libk3b/cddb/k3bcddb.cpp b/libk3b/cddb/k3bcddb.cpp new file mode 100644 index 0000000..a0e4fe1 --- /dev/null +++ b/libk3b/cddb/k3bcddb.cpp @@ -0,0 +1,280 @@ +/* + * + * $Id: k3bcddb.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "k3bcddb.h" +#include "k3bcddbhttpquery.h" +#include "k3bcddbpquery.h" +#include "k3bcddblocalquery.h" +#include "k3bcddblocalsubmit.h" + +#include +#include +#include "k3bcddbmultientriesdialog.h" + + +K3bCddb::K3bCddb( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + m_httpQuery = 0; + m_cddbpQuery = 0; + m_localQuery = 0; + m_localSubmit = 0; + + m_lastUsedQuery = 0; +} + + +K3bCddb::~K3bCddb() +{ +} + + +void K3bCddb::readConfig( KConfig* c ) +{ + c->setGroup( "Cddb" ); + + m_bRemoteCddbQuery = c->readBoolEntry( "use remote cddb", true ); + m_bLocalCddbQuery = c->readBoolEntry( "use local cddb query", false ); + + // old config <= 0.7.3 + QStringList cddbpServer = c->readListEntry( "cddbp server" ); + QStringList httpServer = c->readListEntry( "http server" ); + + // new config + m_cddbServer = c->readListEntry( "cddb server" ); + + m_localCddbDirs = c->readPathListEntry( "local cddb dirs" ); + + m_bUseManualCgiPath = c->readBoolEntry( "use manual cgi path", false ); + m_cgiPath = c->readEntry( "cgi path", "/~cddb/cddb.cgi" ); + + if( m_localCddbDirs.isEmpty() ) + m_localCddbDirs.append( "~/.cddb/" ); + + // old config <= 0.7.3 + if( !httpServer.isEmpty() ) { + for( QStringList::iterator it = httpServer.begin(); it != httpServer.end(); ++it ) { + m_cddbServer.append( "Http " + *it ); + } + } + if( !cddbpServer.isEmpty() ) { + for( QStringList::iterator it = cddbpServer.begin(); it != cddbpServer.end(); ++it ) { + m_cddbServer.append( "Cddbp " + *it ); + } + } + + if( m_cddbServer.isEmpty() ) + m_cddbServer.append( "Http freedb2.org:80" ); +} + + +void K3bCddb::query( const K3bDevice::Toc& toc ) +{ + m_toc = toc; + + if( m_bLocalCddbQuery ) { + m_iCurrentQueriedLocalDir = 0; + QTimer::singleShot( 0, this, SLOT(localQuery()) ); + } + else if( m_bRemoteCddbQuery ) { + m_iCurrentQueriedServer = 0; + QTimer::singleShot( 0, this, SLOT(remoteQuery()) ); + } + else { + QTimer::singleShot( 0, this, SLOT(slotNoEntry()) ); + } +} + + +void K3bCddb::slotNoEntry() +{ + emit queryFinished( K3bCddbQuery::NO_ENTRY_FOUND ); +} + + +void K3bCddb::remoteQuery() +{ + K3bCddbQuery* q = getQuery( m_cddbServer[m_iCurrentQueriedServer] ); + q->query(m_toc); +} + + +void K3bCddb::slotMultibleMatches( K3bCddbQuery* query ) +{ + K3bCddbResultHeader hdr = K3bCddbMultiEntriesDialog::selectCddbEntry( query, 0 ); + if( !hdr.discid.isEmpty() ) + query->queryMatch( hdr ); + else + emit queryFinished( K3bCddbQuery::CANCELED ); +} + + +void K3bCddb::slotQueryFinished( K3bCddbQuery* query ) +{ + m_lastUsedQuery = query; + + if( query->error() == K3bCddbQuery::SUCCESS ) { + m_lastResult = m_lastUsedQuery->result(); + + // make sure the result has the requested discid since otherwise local saving does not make much sense + m_lastResult.discid = QString::number( m_toc.discId(), 16 ).rightJustify( 8, '0' ); + + emit queryFinished( K3bCddbQuery::SUCCESS ); + } + else if( query == m_localQuery ) { + m_iCurrentQueriedLocalDir++; + if( m_iCurrentQueriedLocalDir < m_localCddbDirs.size() ) + localQuery(); + else if( m_bRemoteCddbQuery ) { + m_iCurrentQueriedServer = 0; + remoteQuery(); + } + else { + emit queryFinished( query->error() ); + } + } + else { + m_iCurrentQueriedServer++; + if( m_iCurrentQueriedServer < m_cddbServer.size() ) { + remoteQuery(); + } + else { + emit queryFinished( query->error() ); + } + } +} + + +K3bCddbQuery* K3bCddb::getQuery( const QString& s ) +{ + QStringList buf = QStringList::split( ":", s.mid( s.find(" ")+1 ) ); + QString server = buf[0]; + int port = buf[1].toInt(); + + if( s.startsWith("Http") ) { + if( !m_httpQuery ) { + m_httpQuery = new K3bCddbHttpQuery( this ); + connect( m_httpQuery, SIGNAL(infoMessage(const QString&)), + this, SIGNAL(infoMessage(const QString&)) ); + connect( m_httpQuery, SIGNAL(queryFinished(K3bCddbQuery*)), + this, SLOT(slotQueryFinished(K3bCddbQuery*)) ); + connect( m_httpQuery, SIGNAL(inexactMatches(K3bCddbQuery*)), + this, SLOT(slotMultibleMatches(K3bCddbQuery*)) ); + } + + m_httpQuery->setServer( server, port ); + m_httpQuery->setCgiPath( m_bUseManualCgiPath ? m_cgiPath : QString::fromLatin1("/~cddb/cddb.cgi") ); + + return m_httpQuery; + } + else { + if( !m_cddbpQuery ) { + m_cddbpQuery = new K3bCddbpQuery( this ); + connect( m_cddbpQuery, SIGNAL(infoMessage(const QString&)), + this, SIGNAL(infoMessage(const QString&)) ); + connect( m_cddbpQuery, SIGNAL(queryFinished(K3bCddbQuery*)), + this, SLOT(slotQueryFinished(K3bCddbQuery*)) ); + connect( m_cddbpQuery, SIGNAL(inexactMatches(K3bCddbQuery*)), + this, SLOT(slotMultibleMatches(K3bCddbQuery*)) ); + } + + m_cddbpQuery->setServer( server, port ); + + return m_cddbpQuery; + } +} + + +void K3bCddb::localQuery() +{ + if( !m_localQuery ) { + m_localQuery = new K3bCddbLocalQuery( this ); + connect( m_localQuery, SIGNAL(infoMessage(const QString&)), + this, SIGNAL(infoMessage(const QString&)) ); + connect( m_localQuery, SIGNAL(queryFinished(K3bCddbQuery*)), + this, SLOT(slotQueryFinished(K3bCddbQuery*)) ); + connect( m_localQuery, SIGNAL(inexactMatches(K3bCddbQuery*)), + this, SLOT(slotMultibleMatches(K3bCddbQuery*)) ); + } + + m_localQuery->setCddbDir( m_localCddbDirs[m_iCurrentQueriedLocalDir] ); + + m_localQuery->query( m_toc ); +} + + +QString K3bCddb::errorString() const +{ + if( !m_lastUsedQuery ) + return "no query"; + + switch( m_lastUsedQuery->error() ) { + case K3bCddbQuery::SUCCESS: + return i18n("Found freedb entry."); + case K3bCddbQuery::NO_ENTRY_FOUND: + return i18n("No entry found"); + case K3bCddbQuery::CONNECTION_ERROR: + return i18n("Error while connecting to host."); + case K3bCddbQuery::WORKING: + return i18n("Working..."); + case K3bCddbQuery::QUERY_ERROR: + case K3bCddbQuery::READ_ERROR: + case K3bCddbQuery::FAILURE: + default: + return i18n("Communication error."); + } +} + + +const K3bCddbResultEntry& K3bCddb::result() const +{ + // return m_lastUsedQuery->result(); + return m_lastResult; +} + + +void K3bCddb::saveEntry( const K3bCddbResultEntry& entry ) +{ + if( !m_localSubmit ) { + m_localSubmit = new K3bCddbLocalSubmit( this ); + connect( m_localSubmit, SIGNAL(submitFinished(K3bCddbSubmit*)), + this, SLOT(slotSubmitFinished(K3bCddbSubmit*)) ); + } + + m_localSubmit->setCddbDir( m_localCddbDirs[0] ); + + m_localSubmit->submit( entry ); +} + + +void K3bCddb::slotSubmitFinished( K3bCddbSubmit* s ) +{ + emit submitFinished( s->error() == K3bCddbSubmit::SUCCESS ); +} + +#include "k3bcddb.moc" + diff --git a/libk3b/cddb/k3bcddb.h b/libk3b/cddb/k3bcddb.h new file mode 100644 index 0000000..86b67c5 --- /dev/null +++ b/libk3b/cddb/k3bcddb.h @@ -0,0 +1,103 @@ +/* + * + * $Id: k3bcddb.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BCDDB_H +#define K3BCDDB_H + +#include +#include +#include + +#include + +#include "k3bcddbresult.h" +#include "k3b_export.h" + +class KConfig; +class K3bCddbQuery; +class K3bCddbHttpQuery; +class K3bCddbpQuery; +class K3bCddbLocalQuery; +class K3bCddbSubmit; +class K3bCddbLocalSubmit; + + +class LIBK3B_EXPORT K3bCddb : public QObject +{ + Q_OBJECT + + public: + K3bCddb( QObject* parent = 0, const char* name = 0 ); + ~K3bCddb(); + + QString errorString() const; + + /** + * Do NOT call this before queryResult has + * been emitted + */ + const K3bCddbResultEntry& result() const; + + public slots: + /** query a cd and connect to the queryFinished signal */ + void query( const K3bDevice::Toc& ); + void readConfig( KConfig* c ); + void saveEntry( const K3bCddbResultEntry& ); + + signals: + void queryFinished( int error ); + void submitFinished( bool success ); + void infoMessage( const QString& ); + + private slots: + void localQuery(); + void remoteQuery(); + void slotQueryFinished( K3bCddbQuery* ); + void slotSubmitFinished( K3bCddbSubmit* ); + void slotMultibleMatches( K3bCddbQuery* ); + void slotNoEntry(); + + private: + K3bCddbQuery* getQuery( const QString& ); + + K3bCddbHttpQuery* m_httpQuery; + K3bCddbpQuery* m_cddbpQuery; + K3bCddbLocalQuery* m_localQuery; + K3bCddbLocalSubmit* m_localSubmit; + + K3bDevice::Toc m_toc; + unsigned int m_iCurrentQueriedServer; + unsigned int m_iCurrentQueriedLocalDir; + + const K3bCddbQuery* m_lastUsedQuery; + K3bCddbResultEntry m_lastResult; + + // config + QStringList m_cddbServer; + QString m_proxyServer; + int m_proxyPort; + QString m_cgiPath; + bool m_bUseProxyServer; + bool m_bUseKdeSettings; + QStringList m_localCddbDirs; + bool m_bSaveCddbEntriesLocally; + bool m_bUseManualCgiPath; + bool m_bRemoteCddbQuery; + bool m_bLocalCddbQuery; +}; + + +#endif diff --git a/libk3b/cddb/k3bcddbhttpquery.cpp b/libk3b/cddb/k3bcddbhttpquery.cpp new file mode 100644 index 0000000..a453c3e --- /dev/null +++ b/libk3b/cddb/k3bcddbhttpquery.cpp @@ -0,0 +1,233 @@ +/* + * + * $Id: k3bcddbhttpquery.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#include "k3bcddbhttpquery.h" + +#include "k3bcddbresult.h" + +#include +#include +#include + +#include +#include +#include +#include + + +K3bCddbHttpQuery::K3bCddbHttpQuery( QObject* parent, const char* name ) + : K3bCddbQuery( parent, name ) +{ + m_server = "freedb.org"; + m_port = 80; + m_cgiPath = "/~cddb/cddb.cgi"; +} + + +K3bCddbHttpQuery::~K3bCddbHttpQuery() +{ +} + + +void K3bCddbHttpQuery::doQuery() +{ + setError( WORKING ); + m_state = QUERY; + + performCommand( queryString() ); +} + + +void K3bCddbHttpQuery::doMatchQuery() +{ + setError( WORKING ); + m_state = READ; + m_parsingBuffer.truncate(0); + + performCommand( QString( "cddb read %1 %2").arg( header().category ).arg( header().discid ) ); +} + + +void K3bCddbHttpQuery::performCommand( const QString& cmd ) +{ + KURL url; + url.setProtocol( "http" ); + url.setHost( m_server ); + url.setPort( m_port ); + url.setPath( m_cgiPath ); + + url.addQueryItem( "cmd", cmd ); + url.addQueryItem( "hello", handshakeString() ); + url.addQueryItem( "proto", "6" ); + + m_data.truncate(0); + + kdDebug() << "(K3bCddbHttpQuery) getting url: " << url.prettyURL() << endl; + + KIO::TransferJob* job = KIO::get( url, false, false ); + + if( !job ) { + setError( CONNECTION_ERROR ); + emit infoMessage( i18n("Could not connect to host %1").arg(m_server) ); + emitQueryFinished(); + return; + } + + connect( job, SIGNAL(data(KIO::Job*, const QByteArray&)), + SLOT(slotData(KIO::Job*, const QByteArray&)) ); + connect( job, SIGNAL(result(KIO::Job*)), + SLOT(slotResult(KIO::Job*)) ); +} + + + +void K3bCddbHttpQuery::slotData( KIO::Job*, const QByteArray& data ) +{ + if( data.size() ) { + QDataStream stream( m_data, IO_WriteOnly | IO_Append ); + stream.writeRawBytes( data.data(), data.size() ); + } +} + + +void K3bCddbHttpQuery::slotResult( KIO::Job* job ) +{ + if( job->error() ) { + emit infoMessage( job->errorString() ); + setError( CONNECTION_ERROR ); + emitQueryFinished(); + return; + } + + QStringList lines = QStringList::split( "\n", QString::fromUtf8( m_data.data(), m_data.size() ) ); + + for( QStringList::const_iterator it = lines.begin(); it != lines.end(); ++it ) { + QString line = *it; + + // kdDebug() << "(K3bCddbHttpQuery) line: " << line << endl; + + switch( m_state ) { + + case QUERY: + if( getCode( line ) == 200 ) { + // parse exact match and send a read command + K3bCddbResultHeader header; + parseMatchHeader( line.mid(4), header ); + + queryMatch( header ); + } + + else if( getCode( line ) == 210 ) { + // TODO: perhaps add an "exact" field to K3bCddbEntry + kdDebug() << "(K3bCddbHttpQuery) Found multiple exact matches" << endl; + + emit infoMessage( i18n("Found multiple exact matches") ); + + m_state = QUERY_DATA; + } + + else if( getCode( line ) == 211 ) { + kdDebug() << "(K3bCddbHttpQuery) Found inexact matches" << endl; + + emit infoMessage( i18n("Found inexact matches") ); + + m_state = QUERY_DATA; + } + + else if( getCode( line ) == 202 ) { + kdDebug() << "(K3bCddbHttpQuery) no match found" << endl; + emit infoMessage( i18n("No match found") ); + setError(NO_ENTRY_FOUND); + m_state = FINISHED; + emitQueryFinished(); + return; + } + + else { + kdDebug() << "(K3bCddbHttpQuery) Error while querying: " << line << endl; + emit infoMessage( i18n("Error while querying") ); + setError(QUERY_ERROR); + m_state = FINISHED; + emitQueryFinished(); + return; + } + break; + + case QUERY_DATA: + if( line.startsWith( "." ) ) { + // finished query + // go on reading + + + // here we have the inexact matches headers and should emit the + // inexactMatches signal + emit inexactMatches( this ); + } + else { + kdDebug() << "(K3bCddbHttpQuery) inexact match: " << line << endl; + + // create a new resultHeader + K3bCddbResultHeader header; + parseMatchHeader( line, header ); + m_inexactMatches.append(header); + } + break; + + case READ: + if( getCode( line ) == 210 ) { + + // we just start parsing the read data + m_state = READ_DATA; + } + + else { + emit infoMessage( i18n("Could not read match") ); + setError(READ_ERROR); + m_state = FINISHED; + emitQueryFinished(); + return; + } + break; + + + case READ_DATA: + + // kdDebug() << "parsing line: " << line << endl; + + if( line.startsWith( "." ) ) { + + kdDebug() << "(K3bCddbHttpQuery query finished." << endl; + + QTextStream strStream( m_parsingBuffer, IO_ReadOnly ); + parseEntry( strStream, result() ); + + setError(SUCCESS); + m_state = FINISHED; + emitQueryFinished(); + return; + } + + else { + m_parsingBuffer.append(line + "\n"); + } + break; + } + } +} + + +#include "k3bcddbhttpquery.moc" diff --git a/libk3b/cddb/k3bcddbhttpquery.h b/libk3b/cddb/k3bcddbhttpquery.h new file mode 100644 index 0000000..b1e544e --- /dev/null +++ b/libk3b/cddb/k3bcddbhttpquery.h @@ -0,0 +1,64 @@ +/* + * + * $Id: k3bcddbhttpquery.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BCDDB_HTTP_QUERY_H +#define K3BCDDB_HTTP_QUERY_H + +#include "k3bcddbquery.h" +#include "k3bcddbresult.h" + +#include + +namespace KIO { + class Job; +} + +class K3bCddbHttpQuery : public K3bCddbQuery +{ + Q_OBJECT + + public: + K3bCddbHttpQuery( QObject* parent = 0, const char* name = 0 ); + ~K3bCddbHttpQuery(); + + public slots: + void setServer( const QString& s, int port = 80 ) { m_server = s; m_port = port; } + void setCgiPath( const QString& p ) { m_cgiPath = p; } + + protected slots: + void doQuery(); + void doMatchQuery(); + void slotResult( KIO::Job* ); + void slotData( KIO::Job*, const QByteArray& data ); + + private: + void performCommand( const QString& ); + + enum State { QUERY, QUERY_DATA, READ, READ_DATA, FINISHED }; + + int m_state; + QString m_server; + int m_port; + QString m_cgiPath; + + QString m_currentlyConnectingServer; + + QByteArray m_data; + QString m_parsingBuffer; +}; + +#endif + diff --git a/libk3b/cddb/k3bcddblocalquery.cpp b/libk3b/cddb/k3bcddblocalquery.cpp new file mode 100644 index 0000000..b3a1264 --- /dev/null +++ b/libk3b/cddb/k3bcddblocalquery.cpp @@ -0,0 +1,129 @@ +/* + * + * $Id: k3bcddblocalquery.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bcddblocalquery.h" + +#include +#include +#include + +#include +#include +#include + + +K3bCddbLocalQuery::K3bCddbLocalQuery( QObject* parent , const char* name ) + : K3bCddbQuery( parent, name ) +{ +} + + +K3bCddbLocalQuery::~K3bCddbLocalQuery() +{ +} + + +void K3bCddbLocalQuery::doQuery() +{ + emit infoMessage( i18n("Searching entry in %1").arg( m_cddbDir ) ); + kapp->processEvents(); //BAD! + + QString path = preparePath( m_cddbDir ); + + kdDebug() << "(K3bCddbLocalQuery) searching in dir " << path << " for " + << QString::number( toc().discId(), 16 ).rightJustify( 8, '0' ) << endl; + + for( QStringList::const_iterator it = categories().begin(); + it != categories().end(); ++it ) { + + QString file = path + *it + "/" + QString::number( toc().discId(), 16 ).rightJustify( 8, '0' ); + + if( QFile::exists( file ) ) { + // found file + + QFile f( file ); + if( !f.open( IO_ReadOnly ) ) { + kdDebug() << "(K3bCddbLocalQuery) Could not open file" << endl; + } + else { + QTextStream t( &f ); + + K3bCddbResultEntry entry; + parseEntry( t, entry ); + K3bCddbResultHeader header; + header.discid = QString::number( toc().discId(), 16 ).rightJustify( 8, '0' ); + header.category = *it; + header.title = entry.cdTitle; + header.artist = entry.cdArtist; + m_inexactMatches.append(header); + } + } + else { + kdDebug() << "(K3bCddbLocalQuery) Could not find local entry in category " << *it << endl; + } + } + + if( m_inexactMatches.count() > 0 ) { + setError( SUCCESS ); + if( m_inexactMatches.count() == 1 ) { + queryMatch( m_inexactMatches.first() ); + } + else { + emit inexactMatches( this ); + } + } + else { + setError( NO_ENTRY_FOUND ); + emit queryFinished( this ); + } +} + + +void K3bCddbLocalQuery::doMatchQuery() +{ + QString path = preparePath( m_cddbDir ) + header().category + "/" + header().discid; + + QFile f( path ); + if( !f.open( IO_ReadOnly ) ) { + kdDebug() << "(K3bCddbLocalQuery) Could not open file" << endl; + setError( READ_ERROR ); + } + else { + QTextStream t( &f ); + + parseEntry( t, result() ); + result().discid = header().discid; + result().category = header().category; + setError( SUCCESS ); + } + emit queryFinished( this ); +} + + +QString K3bCddbLocalQuery::preparePath( const QString& p ) +{ + QString path = p; + if( path.startsWith( "~" ) ) + path.replace( 0, 1, QDir::homeDirPath() ); + else if( !path.startsWith( "/" ) ) + path.prepend( QDir::homeDirPath() ); + if( path[path.length()-1] != '/' ) + path.append( "/" ); + + return path; +} + +#include "k3bcddblocalquery.moc" diff --git a/libk3b/cddb/k3bcddblocalquery.h b/libk3b/cddb/k3bcddblocalquery.h new file mode 100644 index 0000000..d68d379 --- /dev/null +++ b/libk3b/cddb/k3bcddblocalquery.h @@ -0,0 +1,48 @@ +/* + * + * $Id: k3bcddblocalquery.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#ifndef K3BCDDB_LOCAL_QUERY_H +#define K3BCDDB_LOCAL_QUERY_H + +#include "k3bcddbquery.h" +#include "k3bcddbresult.h" + +#include + + +class K3bCddbLocalQuery : public K3bCddbQuery +{ + Q_OBJECT + + public: + K3bCddbLocalQuery( QObject* parent = 0, const char* name = 0 ); + ~K3bCddbLocalQuery(); + + public slots: + void setCddbDir( const QString& dir ) { m_cddbDir = dir; } + + protected: + void doQuery(); + void doMatchQuery(); + + private: + QString preparePath( const QString& p ); + + QString m_cddbDir; +}; + +#endif diff --git a/libk3b/cddb/k3bcddblocalsubmit.cpp b/libk3b/cddb/k3bcddblocalsubmit.cpp new file mode 100644 index 0000000..f2d1e69 --- /dev/null +++ b/libk3b/cddb/k3bcddblocalsubmit.cpp @@ -0,0 +1,102 @@ +/* + * + * $Id: k3bcddblocalsubmit.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#include "k3bcddblocalsubmit.h" + +#include +#include +#include + +#include +#include + + +K3bCddbLocalSubmit::K3bCddbLocalSubmit( QObject* parent, const char* name ) + : K3bCddbSubmit( parent, name ) +{ +} + + +K3bCddbLocalSubmit::~K3bCddbLocalSubmit() +{ +} + + +void K3bCddbLocalSubmit::doSubmit() +{ + QString path = m_cddbDir; + if( path.startsWith( "~" ) ) + path.replace( 0, 1, QDir::homeDirPath() + "/" ); + else if( !path.startsWith( "/" ) ) + path.prepend( QDir::homeDirPath() + "/" ); + if( path[path.length()-1] != '/' ) + path.append( "/" ); + + if( !QFile::exists( path ) && !QDir().mkdir( path ) ) { + kdDebug() << "(K3bCddbLocalSubmit) could not create directory: " << path << endl; + setError( IO_ERROR ); + emit submitFinished( this ); + return; + } + + if( QFile::exists( path ) ) { + // if the category dir does not exists + // create it + + path += resultEntry().category; + + if( !QFile::exists( path ) ) { + if( !QDir().mkdir( path ) ) { + kdDebug() << "(K3bCddbLocalSubmit) could not create directory: " << path << endl; + setError( IO_ERROR ); + emit submitFinished( this ); + return; + } + } + + // we always overwrite existing entries + path += "/" + resultEntry().discid; + QFile entryFile( path ); + if( entryFile.exists() ) { + kdDebug() << "(K3bCddbLocalSubmit) file already exists: " << path << endl; + } + + if( !entryFile.open( IO_WriteOnly ) ) { + kdDebug() << "(K3bCddbLocalSubmit) could not create file: " << path << endl; + setError( IO_ERROR ); + emit submitFinished( this ); + } + else { + kdDebug() << "(K3bCddbLocalSubmit) creating file: " << path << endl; + QTextStream entryStream( &entryFile ); + entryStream.setEncoding( QTextStream::UnicodeUTF8 ); + entryStream << resultEntry().rawData; + entryFile.close(); + + setError( SUCCESS ); + emit submitFinished( this ); + } + } + else { + kdDebug() << "(K3bCddbLocalSubmit) could not find directory: " << path << endl; + setError( IO_ERROR ); + emit infoMessage( i18n("Could not find directory: %1").arg(path) ); + emit submitFinished( this ); + } +} + +#include "k3bcddblocalsubmit.moc" diff --git a/libk3b/cddb/k3bcddblocalsubmit.h b/libk3b/cddb/k3bcddblocalsubmit.h new file mode 100644 index 0000000..8b7ea91 --- /dev/null +++ b/libk3b/cddb/k3bcddblocalsubmit.h @@ -0,0 +1,43 @@ +/* + * + * $Id: k3bcddblocalsubmit.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BCDDB_LOCAL_SUBMIT_H +#define K3BCDDB_LOCAL_SUBMIT_H + +#include "k3bcddbsubmit.h" + +#include + + +class K3bCddbLocalSubmit : public K3bCddbSubmit +{ + Q_OBJECT + + public: + K3bCddbLocalSubmit( QObject* parent = 0, const char* name = 0 ); + ~K3bCddbLocalSubmit(); + + public slots: + void setCddbDir( const QString& dir ) { m_cddbDir = dir; } + + protected slots: + void doSubmit(); + + private: + QString m_cddbDir; +}; + +#endif diff --git a/libk3b/cddb/k3bcddbmultientriesdialog.cpp b/libk3b/cddb/k3bcddbmultientriesdialog.cpp new file mode 100644 index 0000000..094176a --- /dev/null +++ b/libk3b/cddb/k3bcddbmultientriesdialog.cpp @@ -0,0 +1,74 @@ +/* + * + * $Id: k3bcddbmultientriesdialog.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bcddbmultientriesdialog.h" + +#include +#include +#include + +#include +#include + + + +K3bCddbMultiEntriesDialog::K3bCddbMultiEntriesDialog( QWidget* parent, const char* name ) + : KDialogBase( Plain, i18n("CDDB Database Entry"), Ok|Cancel, Ok, parent, name ) +{ + QFrame* frame = plainPage(); + QVBoxLayout* layout = new QVBoxLayout( frame ); + layout->setAutoAdd( true ); + layout->setSpacing( spacingHint() ); + layout->setMargin( 0 ); + + QLabel* infoLabel = new QLabel( i18n("K3b found multiple inexact CDDB entries. Please select one."), frame ); + infoLabel->setAlignment( WordBreak ); + + m_listBox = new KListBox( frame, "list_box"); + + setMinimumSize( 280, 200 ); +} + +K3bCddbResultHeader K3bCddbMultiEntriesDialog::selectCddbEntry( K3bCddbQuery* query, QWidget* parent ) +{ + K3bCddbMultiEntriesDialog d( parent ); + + const QValueList headers = query->getInexactMatches(); + + int i = 1; + for( QValueListConstIterator it = headers.begin(); + it != headers.end(); ++it ) { + d.m_listBox->insertItem( QString::number(i) + " " + + (*it).artist + " - " + + (*it).title + " (" + + (*it).category + ")" ); + ++i; + } + + d.m_listBox->setSelected( 0, true ); + + if( d.exec() == QDialog::Accepted ) + return headers[ d.m_listBox->currentItem() >= 0 ? d.m_listBox->currentItem() : 0 ]; + else + return K3bCddbResultHeader(); +} + + +K3bCddbMultiEntriesDialog::~K3bCddbMultiEntriesDialog(){ +} + + +#include "k3bcddbmultientriesdialog.moc" diff --git a/libk3b/cddb/k3bcddbmultientriesdialog.h b/libk3b/cddb/k3bcddbmultientriesdialog.h new file mode 100644 index 0000000..15cc6f8 --- /dev/null +++ b/libk3b/cddb/k3bcddbmultientriesdialog.h @@ -0,0 +1,48 @@ +/* + * + * $Id: k3bcddbmultientriesdialog.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BCDDBMULTIENTRIESDIALOG_H +#define K3BCDDBMULTIENTRIESDIALOG_H + +#include + +#include "k3bcddbquery.h" +#include "k3bcddbresult.h" + + +class QStringList; +class KListBox; + +/** + *@author Sebastian Trueg + */ +class K3bCddbMultiEntriesDialog : public KDialogBase +{ + Q_OBJECT + + public: + ~K3bCddbMultiEntriesDialog(); + + static K3bCddbResultHeader selectCddbEntry( K3bCddbQuery* query, QWidget* parent = 0 ); + + protected: + K3bCddbMultiEntriesDialog( QWidget* parent = 0, const char* name = 0); + + private: + KListBox *m_listBox; +}; + +#endif diff --git a/libk3b/cddb/k3bcddbpquery.cpp b/libk3b/cddb/k3bcddbpquery.cpp new file mode 100644 index 0000000..fefc8e4 --- /dev/null +++ b/libk3b/cddb/k3bcddbpquery.cpp @@ -0,0 +1,278 @@ +/* + * + * $Id: k3bcddbpquery.cpp 619556 2007-01-03 17:38:12Z trueg $ + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bcddbpquery.h" + +#include +#include +#include + +#include +#include + + + + +K3bCddbpQuery::K3bCddbpQuery( QObject* parent, const char* name ) + :K3bCddbQuery( parent, name ) +{ + m_socket = new QSocket( this ); + m_stream.setDevice( m_socket ); + m_stream.setEncoding( QTextStream::UnicodeUTF8 ); + + connect( m_socket, SIGNAL(connected()), this, SLOT(slotConnected()) ); + connect( m_socket, SIGNAL(hostFound()), this, SLOT(slotHostFound()) ); + connect( m_socket, SIGNAL(connectionClosed()), this, SLOT(slotConnectionClosed()) ); + connect( m_socket, SIGNAL(error(int)), this, SLOT(slotError(int)) ); + connect( m_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()) ); +} + + +K3bCddbpQuery::~K3bCddbpQuery() +{ + delete m_socket; +} + +void K3bCddbpQuery::doQuery() +{ + setError( WORKING ); + + m_state = GREETING; + + // connect to the server + + m_socket->connectToHost( m_server, m_port ); + emit infoMessage( i18n("Searching %1 on port %2").arg(m_server).arg(m_port) ); +} + + +void K3bCddbpQuery::doMatchQuery() +{ + // we should still be connected + // TODO: check this + + QString read = QString( "cddb read %1 %2").arg( header().category ).arg( header().discid ); + + m_state = READ; + m_parsingBuffer = ""; + + kdDebug() << "(K3bCddbpQuery) Read: " << read << endl; + + m_stream << read << endl << flush; +} + + +void K3bCddbpQuery::slotHostFound() +{ + emit infoMessage( i18n("Host found") ); +} + + +void K3bCddbpQuery::slotConnected() +{ + emit infoMessage( i18n("Connected") ); +} + + +void K3bCddbpQuery::slotConnectionClosed() +{ + emit infoMessage( i18n("Connection closed") ); + emitQueryFinished(); +} + + +void K3bCddbpQuery::cddbpQuit() +{ + m_state = QUIT; + m_stream << "quit" << endl << flush; +} + + +void K3bCddbpQuery::slotReadyRead() +{ + while( m_socket->canReadLine() ) { + QString line = m_stream.readLine(); + + // kdDebug() << "(K3bCddbpQuery) line: " << line << endl; + + switch( m_state ) { + case GREETING: + if( getCode( line ) == 200 || getCode( line ) == 201) { + emit infoMessage( i18n("OK, read access") ); + m_state = HANDSHAKE; + + m_stream << "cddb hello " << handshakeString() << endl << flush; + } + + else { + emit infoMessage( i18n("Connection refused") ); + setError( CONNECTION_ERROR ); + m_socket->close(); + } + break; + + case HANDSHAKE: + if( getCode( line ) == 200 ) { + emit infoMessage( i18n("Handshake successful") ); + + m_state = PROTO; + + m_stream << "proto 6" << endl << flush; + } + + else { + emit infoMessage( i18n("Handshake failed") ); // server closes connection + setError( CONNECTION_ERROR ); + m_socket->close(); // just to be sure + } + break; + + case PROTO: + { + if( getCode( line ) == 501 ) { + kdDebug() << "(K3bCddbpQuery) illigal protocol level!" << endl; + } + + // just ignore the reply since it's not important for the functionality + m_state = QUERY; + + m_stream << queryString() << endl << flush; + break; + } + + case QUERY: + if( getCode( line ) == 200 ) { + // parse exact match and send a read command + K3bCddbResultHeader header; + parseMatchHeader( line.mid( 4 ), header ); + + emit infoMessage( i18n("Found exact match") ); + + queryMatch( header ); + } + + else if( getCode( line ) == 210 ) { + // TODO: perhaps add an "exact" field to K3bCddbEntry + kdDebug() << "(K3bCddbpQuery) Found multiple exact matches" << endl; + + emit infoMessage( i18n("Found multiple exact matches") ); + + m_state = QUERY_DATA; + } + + else if( getCode( line ) == 211 ) { + kdDebug() << "(K3bCddbpQuery) Found inexact matches" << endl; + + emit infoMessage( i18n("Found inexact matches") ); + + m_state = QUERY_DATA; + } + + else if( getCode( line ) == 202 ) { + kdDebug() << "(K3bCddbpQuery) no match found" << endl; + emit infoMessage( i18n("No match found") ); + setError( NO_ENTRY_FOUND ); + cddbpQuit(); + } + + else { + kdDebug() << "(K3bCddbpQuery) Error while querying: " << line << endl; + emit infoMessage( i18n("Error while querying") ); + setError( QUERY_ERROR ); + cddbpQuit(); + } + break; + + case QUERY_DATA: + if( line.startsWith( "." ) ) { + // finished query + // go on reading + + emit inexactMatches( this ); + return; + } + else { + kdDebug() << "(K3bCddbpQuery) inexact match: " << line << endl; + K3bCddbResultHeader header; + parseMatchHeader( line, header ); + m_inexactMatches.append( header ); + } + break; + + case READ: + if( getCode( line ) == 210 ) { + + // we just start parsing the read data + m_state = READ_DATA; + } + + else { + emit infoMessage( i18n("Could not read match") ); + setError( READ_ERROR ); + cddbpQuit(); + } + break; + + + case READ_DATA: + + // kdDebug() << "(K3bCddbpQuery) parsing line: " << line << endl; + + if( line.startsWith( "." ) ) { + + kdDebug() << "(K3bCddbpQuery) query finished." << endl; + + QTextStream strStream( m_parsingBuffer, IO_ReadOnly ); + parseEntry( strStream, result() ); + + setError( SUCCESS ); + cddbpQuit(); + } + + else { + m_parsingBuffer.append(line + "\n"); + } + break; + + case QUIT: + // no parsing needed + break; + } + } +} + + +void K3bCddbpQuery::slotError( int e ) +{ + switch(e) { + case QSocket::ErrConnectionRefused: + kdDebug() << i18n("Connection to %1 refused").arg( m_server ) << endl; + emit infoMessage( i18n("Connection to %1 refused").arg( m_server ) ); + break; + case QSocket::ErrHostNotFound: + kdDebug() << i18n("Could not find host %1").arg( m_server ) << endl; + emit infoMessage( i18n("Could not find host %1").arg( m_server ) ); + break; + case QSocket::ErrSocketRead: + kdDebug() << i18n("Error while reading from %1").arg( m_server ) << endl; + emit infoMessage( i18n("Error while reading from %1").arg( m_server ) ); + break; + } + + m_socket->close(); + emitQueryFinished(); +} + +#include "k3bcddbpquery.moc" diff --git a/libk3b/cddb/k3bcddbpquery.h b/libk3b/cddb/k3bcddbpquery.h new file mode 100644 index 0000000..78fe5df --- /dev/null +++ b/libk3b/cddb/k3bcddbpquery.h @@ -0,0 +1,62 @@ +/* + * + * $Id: k3bcddbpquery.h 619556 2007-01-03 17:38:12Z trueg $ + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BCDDBP_QUERY_H +#define K3BCDDBP_QUERY_H + +#include "k3bcddbquery.h" +#include "k3bcddbresult.h" + +#include +#include +#include + +class QSocket; + +class K3bCddbpQuery : public K3bCddbQuery +{ + Q_OBJECT + + public: + K3bCddbpQuery( QObject* parent = 0, const char* name = 0 ); + ~K3bCddbpQuery(); + + public slots: + void setServer( const QString& s, int port = 8080 ) { m_server = s; m_port = port; } + + protected slots: + void slotHostFound(); + void slotConnected(); + void slotConnectionClosed(); + void slotReadyRead(); + void slotError( int e ); + void doQuery(); + void doMatchQuery(); + + private: + void cddbpQuit(); + enum State { GREETING, HANDSHAKE, PROTO, QUERY, QUERY_DATA, READ, READ_DATA, QUIT }; + + int m_state; + QString m_server; + int m_port; + + QSocket* m_socket; + QTextStream m_stream; + + QString m_parsingBuffer; +}; + +#endif diff --git a/libk3b/cddb/k3bcddbquery.cpp b/libk3b/cddb/k3bcddbquery.cpp new file mode 100644 index 0000000..783f9a4 --- /dev/null +++ b/libk3b/cddb/k3bcddbquery.cpp @@ -0,0 +1,275 @@ +/* + * + * $Id: k3bcddbquery.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#include "k3bcddbquery.h" + +#include "k3bcddbresult.h" + +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include + + + + +K3bCddbQuery::K3bCddbQuery( QObject* parent, const char* name ) + : QObject(parent, name) +{ + m_bQueryFinishedEmited = false; +} + + +K3bCddbQuery::~K3bCddbQuery() +{ +} + + +void K3bCddbQuery::query( const K3bDevice::Toc& toc ) +{ + m_bQueryFinishedEmited = false; + m_toc = toc; + m_inexactMatches.clear(); + + QTimer::singleShot( 0, this, SLOT(doQuery()) ); +} + + +void K3bCddbQuery::queryMatch( const K3bCddbResultHeader& header ) +{ + m_header = header; + m_result = K3bCddbResultEntry(); + m_result.category = header.category; + m_result.discid = header.discid; + + QTimer::singleShot( 0, this, SLOT(doMatchQuery()) ); +} + + +const QStringList& K3bCddbQuery::categories() +{ + static QStringList s_cat = QStringList::split( ",", "rock,blues,misc,classical," + "country,data,folk,jazz,newage,reggae,soundtrack" ); + return s_cat; +} + + +bool K3bCddbQuery::parseEntry( QTextStream& stream, K3bCddbResultEntry& entry ) +{ + entry.rawData = ""; + + stream.setEncoding( QTextStream::UnicodeUTF8 ); + + // parse data + QString line; + while( !(line = stream.readLine()).isNull() ) { + entry.rawData.append(line + "\n"); + + // !all fields may be splitted into several lines! + + if( line.startsWith( "DISCID" ) ) { + // TODO: this could be several discids separated by comma! + } + + else if( line.startsWith( "DYEAR" ) ) { + QString year = line.mid( 6 ); + if( year.length() == 4 ) + entry.year = year.toInt(); + } + + else if( line.startsWith( "DGENRE" ) ) { + entry.genre = line.mid( 7 ); + } + + else if( line.startsWith( "DTITLE" ) ) { + entry.cdTitle += line.mid( 7 ); + } + + else if( line.startsWith( "TTITLE" ) ) { + int eqSgnPos = line.find( "=" ); + bool ok; + uint trackNum = (uint)line.mid( 6, eqSgnPos - 6 ).toInt( &ok ); + if( !ok ) + kdDebug() << "(K3bCddbQuery) !!! PARSE ERROR: " << line << endl; + else { + // kdDebug() << "(K3bCddbQuery) Track title for track " << trackNum << endl; + + // make sure the list is big enough + while( entry.titles.count() <= trackNum ) + entry.titles.append( "" ); + + entry.titles[trackNum] += line.mid( eqSgnPos+1 ); + } + } + + else if( line.startsWith( "EXTD" ) ) { + entry.cdExtInfo += line.mid( 5 ); + } + + else if( line.startsWith( "EXTT" ) ) { + int eqSgnPos = line.find( "=" ); + bool ok; + uint trackNum = (uint)line.mid( 4, eqSgnPos - 4 ).toInt( &ok ); + if( !ok ) + kdDebug() << "(K3bCddbQuery) !!! PARSE ERROR: " << line << endl; + else { + // kdDebug() << "(K3bCddbQuery) Track extr track " << trackNum << endl; + + // make sure the list is big enough + while( entry.extInfos.count() <= trackNum ) + entry.extInfos.append( "" ); + + entry.extInfos[trackNum] += line.mid( eqSgnPos+1 ); + } + } + + else if( line.startsWith( "#" ) ) { + // kdDebug() << "(K3bCddbQuery) comment: " << line << endl; + } + + else { + kdDebug() << "(K3bCddbQuery) Unknown field: " << line << endl; + } + } + + // now split the titles in the last added match + // if no " / " delimiter is present title and artist are the same + // ------------------------------------------------------------------- + QString fullTitle = entry.cdTitle; + int splitPos = fullTitle.find( " / " ); + if( splitPos < 0 ) + entry.cdArtist = fullTitle; + else { + // split + entry.cdTitle = fullTitle.mid( splitPos + 3 ); + entry.cdArtist = fullTitle.left( splitPos ); + } + + + for( QStringList::iterator it = entry.titles.begin(); + it != entry.titles.end(); ++it ) { + QString fullTitle = *it; + int splitPos = fullTitle.find( " / " ); + if( splitPos < 0 ) + entry.artists.append( entry.cdArtist ); + else { + // split + *it = fullTitle.mid( splitPos + 3 ); + entry.artists.append( fullTitle.left( splitPos ) ); + } + } + + + // replace all "\\n" with "\n" + for( QStringList::iterator it = entry.titles.begin(); + it != entry.titles.end(); ++it ) { + (*it).replace( "\\\\\\\\n", "\\n" ); + } + + for( QStringList::iterator it = entry.artists.begin(); + it != entry.artists.end(); ++it ) { + (*it).replace( "\\\\\\\\n", "\\n" ); + } + + for( QStringList::iterator it = entry.extInfos.begin(); + it != entry.extInfos.end(); ++it ) { + (*it).replace( "\\\\\\\\n", "\\n" ); + } + + entry.cdTitle.replace( "\\\\\\\\n", "\\n" ); + entry.cdArtist.replace( "\\\\\\\\n", "\\n" ); + entry.cdExtInfo.replace( "\\\\\\\\n", "\\n" ); + entry.genre.replace( "\\\\\\\\n", "\\n" ); + + return true; +} + + +int K3bCddbQuery::getCode( const QString& line ) +{ + bool ok; + int code = line.left( 3 ).toInt( &ok ); + if( !ok ) + code = -1; + return code; +} + + +QString K3bCddbQuery::handshakeString() const +{ + QString user( getenv("USER") ); + QString host( getenv("HOST") ); + if( user.isEmpty() ) + user = "kde-user"; + if( host.isEmpty() ) + host = "kde-host"; + + return QString("%1 %2 K3b %3").arg(user).arg(host).arg(kapp->aboutData()->version()); +} + + +QString K3bCddbQuery::queryString() const +{ + QString query = "cddb query " + + QString::number( m_toc.discId(), 16 ).rightJustify( 8, '0' ) + + " " + + QString::number( (unsigned int)m_toc.count() ); + + for( K3bDevice::Toc::const_iterator it = m_toc.begin(); it != m_toc.end(); ++it ) { + query.append( QString( " %1" ).arg( (*it).firstSector().lba() ) ); + } + + query.append( QString( " %1" ).arg( m_toc.length().lba() / 75 ) ); + + return query; +} + + +bool K3bCddbQuery::parseMatchHeader( const QString& line, K3bCddbResultHeader& header ) +{ + // format: category id title + // where title could be artist and title splitted with a / + header.category = line.section( ' ', 0, 0 ); + header.discid = line.section( ' ', 1, 1 ); + header.title = line.mid( header.category.length() + header.discid.length() + 2 ); + int slashPos = header.title.find( "/" ); + if( slashPos > 0 ) { + header.artist = header.title.left(slashPos).stripWhiteSpace(); + header.title = header.title.mid( slashPos+1 ).stripWhiteSpace(); + } + return true; +} + + +void K3bCddbQuery::emitQueryFinished() +{ + if( !m_bQueryFinishedEmited ) { + m_bQueryFinishedEmited = true; + emit queryFinished( this ); + } +} + + +#include "k3bcddbquery.moc" diff --git a/libk3b/cddb/k3bcddbquery.h b/libk3b/cddb/k3bcddbquery.h new file mode 100644 index 0000000..569e882 --- /dev/null +++ b/libk3b/cddb/k3bcddbquery.h @@ -0,0 +1,115 @@ +/* + * + * $Id: k3bcddbquery.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BCDDB_QUERY_H +#define K3BCDDB_QUERY_H + +#include +#include +#include + +#include "k3bcddbresult.h" + +#include +#include "k3b_export.h" + + +class LIBK3B_EXPORT K3bCddbQuery : public QObject +{ + Q_OBJECT + + public: + K3bCddbQuery( QObject* parent = 0, const char* name = 0 ); + virtual ~K3bCddbQuery(); + + void query( const K3bDevice::Toc& ); + + /** + * Use this if the query returned multiple matches + */ + void queryMatch( const K3bCddbResultHeader& ); + + const K3bCddbResultEntry& result() const { return m_result; } + + /** + * After emitting the signal inexactMatches one has to choose one + * of these entries and query it with queryInexactMatch + */ + const QValueList& getInexactMatches() const { return m_inexactMatches; } + + static const QStringList& categories(); + + enum Error { SUCCESS = 0, + CANCELED, + NO_ENTRY_FOUND, + CONNECTION_ERROR, + QUERY_ERROR, + READ_ERROR, + FAILURE, + WORKING }; + + int error() const { return m_error; } + + signals: + /** + * This gets emitted if a single entry has been found or + * no entry has been found. + */ + void queryFinished( K3bCddbQuery* ); + + /** + * This gets emitted if multiple entries have been found. + * Call queryInexactMatch() after receiving it. + */ + void inexactMatches( K3bCddbQuery* ); + + void infoMessage( const QString& ); + + protected slots: + virtual void doQuery() = 0; + virtual void doMatchQuery() = 0; + + protected: + const K3bDevice::Toc& toc() const { return m_toc; } + K3bCddbResultHeader& header() { return m_header; } + K3bCddbResultEntry& result() { return m_result; } + void setError( int e ) { m_error = e; } + + bool parseEntry( QTextStream&, K3bCddbResultEntry& ); + int getCode( const QString& ); + QString handshakeString() const; + QString queryString() const; + bool parseMatchHeader( const QString& line, K3bCddbResultHeader& header ); + + /** + * since I'm not quite sure when the socket will emit connectionClosed + * this method makes sure the queryFinished signal + * gets emited only once. + */ + void emitQueryFinished(); + + QValueList m_inexactMatches; + + private: + K3bDevice::Toc m_toc; + K3bCddbResultEntry m_result; + K3bCddbResultHeader m_header; + int m_error; + + bool m_bQueryFinishedEmited; +}; + +#endif diff --git a/libk3b/cddb/k3bcddbresult.cpp b/libk3b/cddb/k3bcddbresult.cpp new file mode 100644 index 0000000..b33b16e --- /dev/null +++ b/libk3b/cddb/k3bcddbresult.cpp @@ -0,0 +1,49 @@ +/* + * + * $Id: k3bcddbresult.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#include "k3bcddbresult.h" + + +K3bCddbResult::K3bCddbResult() +{ +} + + +void K3bCddbResult::clear() +{ + m_entries.clear(); +} + + +int K3bCddbResult::foundEntries() const +{ + return m_entries.count(); +} + +const K3bCddbResultEntry& K3bCddbResult::entry( unsigned int number ) const +{ + if( number >= m_entries.count() ) + return m_emptyEntry; + + return m_entries[number]; +} + + +void K3bCddbResult::addEntry( const K3bCddbResultEntry& entry ) +{ + m_entries.append( entry ); +} diff --git a/libk3b/cddb/k3bcddbresult.h b/libk3b/cddb/k3bcddbresult.h new file mode 100644 index 0000000..46dcb9a --- /dev/null +++ b/libk3b/cddb/k3bcddbresult.h @@ -0,0 +1,79 @@ +/* + * + * $Id: k3bcddbresult.h 768492 2008-01-30 08:39:42Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#ifndef K3B_CDDB_RESULT_H +#define K3B_CDDB_RESULT_H + + +#include +#include "k3b_export.h" + + +class LIBK3B_EXPORT K3bCddbResultHeader +{ + public: + QString category; + QString title; + QString artist; + QString discid; +}; + + +class LIBK3B_EXPORT K3bCddbResultEntry +{ + public: + // just to set a default + K3bCddbResultEntry() + : category("misc"), + year(0) { + } + + QStringList titles; + QStringList artists; + QStringList extInfos; + + QString cdTitle; + QString cdArtist; + QString cdExtInfo; + + QString genre; + QString category; + int year; + QString discid; + + QString rawData; +}; + + +class LIBK3B_EXPORT K3bCddbResult +{ + public: + K3bCddbResult(); + // K3bCddbQuery( const K3bCddbQuery& ); + + void clear(); + void addEntry( const K3bCddbResultEntry& = K3bCddbResultEntry() ); + const K3bCddbResultEntry& entry( unsigned int number = 0 ) const; + int foundEntries() const; + + private: + QValueList m_entries; + + K3bCddbResultEntry m_emptyEntry; +}; + +#endif diff --git a/libk3b/cddb/k3bcddbsubmit.cpp b/libk3b/cddb/k3bcddbsubmit.cpp new file mode 100644 index 0000000..a04dbcb --- /dev/null +++ b/libk3b/cddb/k3bcddbsubmit.cpp @@ -0,0 +1,84 @@ +/* + * + * $Id: k3bcddbsubmit.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bcddbsubmit.h" + +#include + + +K3bCddbSubmit::K3bCddbSubmit( QObject* parent, const char* name ) + : QObject( parent, name ) +{ +} + + +K3bCddbSubmit::~K3bCddbSubmit() +{ +} + + +void K3bCddbSubmit::submit( const K3bCddbResultEntry& entry ) +{ + m_resultEntry = entry; + + if( m_resultEntry.rawData.isEmpty() ) + createDataStream( m_resultEntry ); + + QTimer::singleShot( 0, this, SLOT(doSubmit()) ); +} + + +void K3bCddbSubmit::createDataStream( K3bCddbResultEntry& entry ) +{ + entry.rawData.truncate(0); + + QTextStream ts( &entry.rawData, IO_WriteOnly ); + + ts << "#" << endl + << "# Submitted via: K3b" << endl + << "#" << endl; + + ts << "DISCID=" << entry.discid << endl + << "DTITLE=" << entry.cdArtist << " / " << entry.cdTitle << endl + << "DYEAR="; + if( entry.year > 0 ) + ts << entry.year; + ts << endl; + ts << "DGENRE=" << entry.genre << endl; + + bool allEqualArtist = true; + for( unsigned int i = 0; i < entry.artists.count(); ++i ) + if( entry.artists[i] != entry.cdArtist && + !entry.artists[i].isEmpty() ) { + allEqualArtist = false; + break; + } + + for( unsigned int i = 0; i < entry.titles.count(); ++i ) { + ts << "TTITLE" << i << "="; + if( !allEqualArtist ) + ts << entry.artists[i] << " / "; + ts << entry.titles[i] << endl; + } + + ts << "EXTD=" << entry.cdExtInfo << endl; + + for( unsigned int i = 0; i < entry.titles.count(); ++i ) { + ts << "EXTT" << i << "=" << entry.extInfos[i] << endl; + } +} + +#include "k3bcddbsubmit.moc" diff --git a/libk3b/cddb/k3bcddbsubmit.h b/libk3b/cddb/k3bcddbsubmit.h new file mode 100644 index 0000000..ff57101 --- /dev/null +++ b/libk3b/cddb/k3bcddbsubmit.h @@ -0,0 +1,60 @@ +/* + * + * $Id: k3bcddbsubmit.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BCDDB_SUBMIT_H +#define K3BCDDB_SUBMIT_H + +#include +#include + +#include "k3bcddbresult.h" + + + +class K3bCddbSubmit : public QObject +{ + Q_OBJECT + + public: + K3bCddbSubmit( QObject* parent = 0, const char* name = 0 ); + virtual ~K3bCddbSubmit(); + + int error() const { return m_error; } + + enum State { SUCCESS, WORKING, IO_ERROR, CONNECTION_ERROR }; + + public slots: + void submit( const K3bCddbResultEntry& ); + + signals: + void infoMessage( const QString& ); + void submitFinished( K3bCddbSubmit* ); + + protected slots: + virtual void doSubmit() = 0; + void setError( int e ) { m_error = e; } + + protected: + K3bCddbResultEntry& resultEntry() { return m_resultEntry; } + + private: + void createDataStream( K3bCddbResultEntry& entry ); + + int m_error; + K3bCddbResultEntry m_resultEntry; +}; + +#endif diff --git a/libk3b/configure.in.in b/libk3b/configure.in.in new file mode 100644 index 0000000..af0c8f5 --- /dev/null +++ b/libk3b/configure.in.in @@ -0,0 +1,3 @@ +AC_CHECK_FUNCS(stat64) +AC_CHECK_HEADERS(sys/vfs.h) +AC_CHECK_HEADERS(sys/statvfs.h) diff --git a/libk3b/core/Makefile.am b/libk3b/core/Makefile.am new file mode 100644 index 0000000..3764d86 --- /dev/null +++ b/libk3b/core/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = -I$(srcdir)/../../libk3bdevice -I$(srcdir)/../plugin -I$(srcdir)/../tools $(all_includes) + +noinst_LTLIBRARIES = libk3bcore.la + +libk3bcore_la_LIBADD = $(LIB_KIO) $(ARTSC_LIB) + +libk3bcore_la_LDFLAGS = $(all_libraries) + +libk3bcore_la_SOURCES = k3bcore.cpp k3bglobals.cpp k3bdefaultexternalprograms.cpp \ + k3bexternalbinmanager.cpp k3bversion.cpp k3bprocess.cpp k3bjob.cpp \ + k3bthread.cpp k3bthreadjob.cpp k3bglobalsettings.cpp k3bsimplejobhandler.cpp + +include_HEADERS = k3bcore.h k3bdefaultexternalprograms.h k3bexternalbinmanager.h \ + k3bprocess.h k3bversion.h k3bglobals.h k3bjob.h k3bthread.h \ + k3bthreadjob.h k3bglobalsettings.h k3bjobhandler.h \ + k3b_export.h k3bjobhandler.h k3bsimplejobhandler.h + +METASOURCES = AUTO + diff --git a/libk3b/core/k3b_export.h b/libk3b/core/k3b_export.h new file mode 100644 index 0000000..b6272f1 --- /dev/null +++ b/libk3b/core/k3b_export.h @@ -0,0 +1,33 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (c) 2005 Laurent Montel + * Copyright (C) 2005-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_EXPORT_H_ +#define _K3B_EXPORT_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef __KDE_HAVE_GCC_VISIBILITY +#define LIBK3B_NO_EXPORT __attribute__ ((visibility("hidden"))) +#define LIBK3B_EXPORT __attribute__ ((visibility("default"))) +#else +#define LIBK3B_NO_EXPORT +#define LIBK3B_EXPORT +#endif + +#endif + diff --git a/libk3b/core/k3bcore.cpp b/libk3b/core/k3bcore.cpp new file mode 100644 index 0000000..c10fec0 --- /dev/null +++ b/libk3b/core/k3bcore.cpp @@ -0,0 +1,375 @@ +/* + * + * $Id: k3bcore.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include + +#include "k3bcore.h" +#include "k3bjob.h" + +#include +#ifdef HAVE_HAL +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + + +static Qt::HANDLE s_guiThreadHandle = QThread::currentThread(); + +// We cannot use QWaitCondition here since the event might be handled faster +// than the thread starts the waiting +class DeviceBlockingEventDoneCondition { +public: + DeviceBlockingEventDoneCondition() + : m_done(false) { + } + + void done() { + m_doneMutex.lock(); + m_done = true; + m_doneMutex.unlock(); + } + + void wait() { + while( true ) { + m_doneMutex.lock(); + bool done = m_done; + m_doneMutex.unlock(); + if( done ) + return; + } + } + +private: + QMutex m_doneMutex; + bool m_done; +}; + +class DeviceBlockingEvent : public QCustomEvent +{ +public: + DeviceBlockingEvent( bool block_, K3bDevice::Device* dev, DeviceBlockingEventDoneCondition* cond_, bool* success_ ) + : QCustomEvent( QEvent::User + 33 ), + block(block_), + device(dev), + cond(cond_), + success(success_) { + } + + bool block; + K3bDevice::Device* device; + DeviceBlockingEventDoneCondition* cond; + bool* success; +}; + + +class K3bCore::Private { +public: + Private() + : version( LIBK3B_VERSION ), + config(0), + deleteConfig(false), + deviceManager(0), + externalBinManager(0), + pluginManager(0), + globalSettings(0) { + } + + K3bVersion version; + KConfig* config; + bool deleteConfig; + K3bDevice::DeviceManager* deviceManager; + K3bExternalBinManager* externalBinManager; + K3bPluginManager* pluginManager; + K3bGlobalSettings* globalSettings; + + QValueList runningJobs; + QValueList blockedDevices; +}; + + + +K3bCore* K3bCore::s_k3bCore = 0; + + + +K3bCore::K3bCore( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + d = new Private(); + + if( s_k3bCore ) + qFatal("ONLY ONE INSTANCE OF K3BCORE ALLOWED!"); + s_k3bCore = this; + + // create the thread widget instance in the GUI thread + K3bThreadWidget::instance(); +} + + +K3bCore::~K3bCore() +{ + s_k3bCore = 0; + + delete d->globalSettings; + delete d; +} + + +K3bDevice::DeviceManager* K3bCore::deviceManager() const +{ + const_cast(this)->initDeviceManager(); + return d->deviceManager; +} + + +K3bExternalBinManager* K3bCore::externalBinManager() const +{ + const_cast(this)->initExternalBinManager(); + return d->externalBinManager; +} + + +K3bPluginManager* K3bCore::pluginManager() const +{ + const_cast(this)->initPluginManager(); + return d->pluginManager; +} + + +K3bGlobalSettings* K3bCore::globalSettings() const +{ + const_cast(this)->initGlobalSettings(); + return d->globalSettings; +} + + +const K3bVersion& K3bCore::version() const +{ + return d->version; +} + + +KConfig* K3bCore::config() const +{ + if( !d->config ) { + kdDebug() << "(K3bCore) opening k3b config file." << endl; + kdDebug() << "(K3bCore) while I am a " << className() << endl; + d->deleteConfig = true; + d->config = new KConfig( "k3brc" ); + } + + return d->config; +} + + +void K3bCore::init() +{ + initGlobalSettings(); + initExternalBinManager(); + initDeviceManager(); + initPluginManager(); + + // load the plugins before doing anything else + // they might add external bins + pluginManager()->loadAll(); + + externalBinManager()->search(); + +#ifdef HAVE_HAL + connect( K3bDevice::HalConnection::instance(), SIGNAL(deviceAdded(const QString&)), + deviceManager(), SLOT(addDevice(const QString&)) ); + connect( K3bDevice::HalConnection::instance(), SIGNAL(deviceRemoved(const QString&)), + deviceManager(), SLOT(removeDevice(const QString&)) ); + QStringList devList = K3bDevice::HalConnection::instance()->devices(); + if( devList.isEmpty() ) + deviceManager()->scanBus(); + else + for( unsigned int i = 0; i < devList.count(); ++i ) + deviceManager()->addDevice( devList[i] ); +#else + deviceManager()->scanBus(); +#endif +} + + +void K3bCore::initGlobalSettings() +{ + if( !d->globalSettings ) + d->globalSettings = new K3bGlobalSettings(); +} + + +void K3bCore::initExternalBinManager() +{ + if( !d->externalBinManager ) { + d->externalBinManager = new K3bExternalBinManager( this ); + K3b::addDefaultPrograms( d->externalBinManager ); + } +} + + +void K3bCore::initDeviceManager() +{ + if( !d->deviceManager ) + d->deviceManager = new K3bDevice::DeviceManager( this ); +} + + +void K3bCore::initPluginManager() +{ + if( !d->pluginManager ) + d->pluginManager = new K3bPluginManager( this ); +} + + +void K3bCore::readSettings( KConfig* cnf ) +{ + KConfig* c = cnf; + if( !c ) + c = config(); + + QString oldGrp = c->group(); + + globalSettings()->readSettings( c ); + deviceManager()->readConfig( c ); + externalBinManager()->readConfig( c ); + + c->setGroup( oldGrp ); +} + + +void K3bCore::saveSettings( KConfig* cnf ) +{ + KConfig* c = cnf; + if( !c ) + c = config(); + + QString oldGrp = c->group(); + + c->setGroup( "General Options" ); + c->writeEntry( "config version", version() ); + + deviceManager()->saveConfig( c ); + externalBinManager()->saveConfig( c ); + d->globalSettings->saveSettings( c ); + + c->setGroup( oldGrp ); +} + + +void K3bCore::registerJob( K3bJob* job ) +{ + d->runningJobs.append( job ); + emit jobStarted( job ); + if( K3bBurnJob* bj = dynamic_cast( job ) ) + emit burnJobStarted( bj ); +} + + +void K3bCore::unregisterJob( K3bJob* job ) +{ + d->runningJobs.remove( job ); + emit jobFinished( job ); + if( K3bBurnJob* bj = dynamic_cast( job ) ) + emit burnJobFinished( bj ); +} + + +bool K3bCore::jobsRunning() const +{ + return !d->runningJobs.isEmpty(); +} + + +const QValueList& K3bCore::runningJobs() const +{ + return d->runningJobs; +} + + +bool K3bCore::blockDevice( K3bDevice::Device* dev ) +{ + if( QThread::currentThread() == s_guiThreadHandle ) { + return internalBlockDevice( dev ); + } + else { + bool success = false; + DeviceBlockingEventDoneCondition w; + QApplication::postEvent( this, new DeviceBlockingEvent( true, dev, &w, &success ) ); + w.wait(); + return success; + } +} + + +void K3bCore::unblockDevice( K3bDevice::Device* dev ) +{ + if( QThread::currentThread() == s_guiThreadHandle ) { + internalUnblockDevice( dev ); + } + else { + DeviceBlockingEventDoneCondition w; + QApplication::postEvent( this, new DeviceBlockingEvent( false, dev, &w, 0 ) ); + w.wait(); + } +} + + +bool K3bCore::internalBlockDevice( K3bDevice::Device* dev ) +{ + if( !d->blockedDevices.contains( dev ) ) { + d->blockedDevices.append( dev ); + return true; + } + else + return false; +} + + +void K3bCore::internalUnblockDevice( K3bDevice::Device* dev ) +{ + d->blockedDevices.remove( dev ); +} + + +void K3bCore::customEvent( QCustomEvent* e ) +{ + if( DeviceBlockingEvent* de = dynamic_cast(e) ) { + if( de->block ) + *de->success = internalBlockDevice( de->device ); + else + internalUnblockDevice( de->device ); + de->cond->done(); + } +} + +#include "k3bcore.moc" diff --git a/libk3b/core/k3bcore.h b/libk3b/core/k3bcore.h new file mode 100644 index 0000000..ce73e32 --- /dev/null +++ b/libk3b/core/k3bcore.h @@ -0,0 +1,181 @@ +/* + * + * $Id: k3bcore.h 733470 2007-11-06 12:10:29Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_CORE_H_ +#define _K3B_CORE_H_ + +#include +#include + +#include "k3b_export.h" + + +#define LIBK3B_VERSION "1.0.5" + +#define k3bcore K3bCore::k3bCore() + + +class K3bExternalBinManager; +class K3bVersion; +class KConfig; +class KAboutData; +class K3bJob; +class K3bBurnJob; +class K3bGlobalSettings; +class K3bPluginManager; +class QCustomEvent; + + +namespace K3bDevice { + class DeviceManager; + class Device; +} + + +/** + * The K3b core takes care of the managers. + * This has been separated from K3bApplication to + * make creating a K3bPart easy. + * This is the heart of the K3b system. Every plugin may use this + * to get the information it needs. + */ +class LIBK3B_EXPORT K3bCore : public QObject +{ + Q_OBJECT + + public: + /** + * Although K3bCore is a singlelton it's constructor is not private to make inheritance + * possible. Just make sure to only create one instance. + */ + K3bCore( QObject* parent = 0, const char* name = 0 ); + virtual ~K3bCore(); + + const QValueList& runningJobs() const; + + /** + * Equals to !runningJobs().isEmpty() + */ + bool jobsRunning() const; + + /** + * The default implementation calls add four initXXX() methods, + * scans for devices, applications, and reads the global settings. + */ + virtual void init(); + + /** + * @param c if 0 K3bCore uses the K3b configuration + */ + virtual void readSettings( KConfig* c = 0 ); + + /** + * @param c if 0 K3bCore uses the K3b configuration + */ + virtual void saveSettings( KConfig* c = 0 ); + + /** + * If this is reimplemented it is recommended to also reimplement + * init(). + */ + virtual K3bDevice::DeviceManager* deviceManager() const; + + /** + * Returns the external bin manager from K3bCore. + * + * By default K3bCore only adds the default programs: + * cdrecord, cdrdao, growisofs, mkisofs, dvd+rw-format, readcd + * + * If you need other programs you have to add them manually like this: + *
externalBinManager()->addProgram( new K3bNormalizeProgram() );
+ */ + K3bExternalBinManager* externalBinManager() const; + K3bPluginManager* pluginManager() const; + + /** + * Global settings used throughout libk3b. Change the settings directly in the + * K3bGlobalSettings object. They will be saved by K3bCore::saveSettings + */ + K3bGlobalSettings* globalSettings() const; + + /** + * returns the version of the library as defined by LIBK3B_VERSION + */ + const K3bVersion& version() const; + + /** + * Default implementation returns the K3b configuration from k3brc. + * Normally this should not be used. + */ + virtual KConfig* config() const; + + /** + * Used by the writing jobs to block a device. + * This makes sure no device is used twice within libk3b + * + * When using this method in a job be aware that reimplementations might + * open dialogs and resulting in a blocking call. + * + * This method calls internalBlockDevice() to do the actual work. + */ + bool blockDevice( K3bDevice::Device* ); + void unblockDevice( K3bDevice::Device* ); + + static K3bCore* k3bCore() { return s_k3bCore; } + + signals: + /** + * Emitted once a new job has been started. This includes burn jobs. + */ + void jobStarted( K3bJob* ); + void burnJobStarted( K3bBurnJob* ); + void jobFinished( K3bJob* ); + void burnJobFinished( K3bBurnJob* ); + + public slots: + /** + * Every running job registers itself with the core. + * For now this is only used to determine if some job + * is running. + */ + void registerJob( K3bJob* job ); + void unregisterJob( K3bJob* job ); + + protected: + /** + * Reimplement this to add additonal checks. + * + * This method is thread safe. blockDevice makes sure + * it is only executed in the GUI thread. + */ + virtual bool internalBlockDevice( K3bDevice::Device* ); + virtual void internalUnblockDevice( K3bDevice::Device* ); + + virtual void initGlobalSettings(); + virtual void initExternalBinManager(); + virtual void initDeviceManager(); + virtual void initPluginManager(); + + virtual void customEvent( QCustomEvent* e ); + + private: + class Private; + Private* d; + + static K3bCore* s_k3bCore; +}; + +#endif diff --git a/libk3b/core/k3bdataevent.h b/libk3b/core/k3bdataevent.h new file mode 100644 index 0000000..b6a4334 --- /dev/null +++ b/libk3b/core/k3bdataevent.h @@ -0,0 +1,48 @@ +/* + * + * $Id: k3bdataevent.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_DATA_EVENT_H +#define K3B_DATA_EVENT_H + +#include + + +/** + * Custom event class for posting events corresponding to the + * K3bJob signals. This is useful for a threaded job since + * in that case it's not possible to emit signals that directly + * change the GUI (see QThread docu). + */ +class K3bDataEvent : public QCustomEvent +{ + public: + // make sure we get not in the way of K3bProgressInfoEvent + static const int EVENT_TYPE = QEvent::User + 100; + + K3bDataEvent( const char* data, int len ) + : QCustomEvent( EVENT_TYPE ), + m_data(data), + m_length(len) + {} + + const char* data() const { return m_data; } + int length() const { return m_length; } + + private: + const char* m_data; + int m_length; +}; + +#endif diff --git a/libk3b/core/k3bdefaultexternalprograms.cpp b/libk3b/core/k3bdefaultexternalprograms.cpp new file mode 100644 index 0000000..b654d22 --- /dev/null +++ b/libk3b/core/k3bdefaultexternalprograms.cpp @@ -0,0 +1,1030 @@ +/* + * + * $Id: k3bdefaultexternalprograms.cpp 731898 2007-11-02 08:22:18Z trueg $ + * Copyright (C) 2003-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bdefaultexternalprograms.h" +#include "k3bexternalbinmanager.h" +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + + +void K3b::addDefaultPrograms( K3bExternalBinManager* m ) +{ + m->addProgram( new K3bCdrecordProgram(false) ); + m->addProgram( new K3bMkisofsProgram() ); + m->addProgram( new K3bReadcdProgram() ); + m->addProgram( new K3bCdrdaoProgram() ); + m->addProgram( new K3bGrowisofsProgram() ); + m->addProgram( new K3bDvdformatProgram() ); + // m->addProgram( new K3bDvdBooktypeProgram() ); +} + + +void K3b::addTranscodePrograms( K3bExternalBinManager* m ) +{ + static const char* transcodeTools[] = { "transcode", + 0, // K3b 1.0 only uses the transcode binary + "tcprobe", + "tccat", + "tcscan", + "tcextract", + "tcdecode", + 0 }; + + for( int i = 0; transcodeTools[i]; ++i ) + m->addProgram( new K3bTranscodeProgram( transcodeTools[i] ) ); +} + + +void K3b::addVcdimagerPrograms( K3bExternalBinManager* m ) +{ + // don't know if we need more vcdTools in the future (vcdxrip) + static const char* vcdTools[] = { "vcdxbuild", + "vcdxminfo", + "vcdxrip", + 0 }; + + for( int i = 0; vcdTools[i]; ++i ) + m->addProgram( new K3bVcdbuilderProgram( vcdTools[i] ) ); +} + + +K3bCdrecordProgram::K3bCdrecordProgram( bool dvdPro ) + : K3bExternalProgram( dvdPro ? "cdrecord-prodvd" : "cdrecord" ), + m_dvdPro(dvdPro) +{ +} + + +// +// This is a hack for Debian based systems which use +// a wrapper cdrecord script to call cdrecord.mmap or cdrecord.shm +// depending on the kernel version. +// For 2.0.x and 2.2.x kernels the shm version is used. In all +// other cases it's the mmap version. +// +// But since it may be that someone manually installed cdrecord +// replacing the wrapper we check if cdrecord is a script. +// +static QString& debianWeirdnessHack( QString& path ) +{ + if( QFile::exists( path + ".mmap" ) ) { + kdDebug() << "(K3bCdrecordProgram) checking for Debian cdrecord wrapper script." << endl; + if( QFileInfo( path ).size() < 1024 ) { + kdDebug() << "(K3bCdrecordProgram) Debian Wrapper script size fits. Checking file." << endl; + QFile f( path ); + f.open( IO_ReadOnly ); + QString s = QTextStream( &f ).read(); + if( s.contains( "cdrecord.mmap" ) && s.contains( "cdrecord.shm" ) ) { + kdDebug() << "(K3bCdrecordProgram) Found Debian Wrapper script." << endl; + QString ext; + if( K3b::kernelVersion().versionString().left(3) > "2.2" ) + ext = ".mmap"; + else + ext = ".shm"; + + kdDebug() << "(K3bCdrecordProgram) Using cdrecord" << ext << endl; + + path += ext; + } + } + } + + return path; +} + + +bool K3bCdrecordProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + bool wodim = false; + QString path = p; + QFileInfo fi( path ); + if( fi.isDir() ) { + if( path[path.length()-1] != '/' ) + path.append("/"); + + if( QFile::exists( path + "wodim" ) ) { + wodim = true; + path += "wodim"; + } + else if( QFile::exists( path + "cdrecord" ) ) { + path += "cdrecord"; + } + else + return false; + } + + debianWeirdnessHack( path ); + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + K3bProcessOutputCollector out( &vp ); + + vp << path << "-version"; + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + int pos = -1; + if( wodim ) { + pos = out.output().find( "Wodim" ); + } + else if( m_dvdPro ) { + pos = out.output().find( "Cdrecord-ProDVD" ); + } + else { + pos = out.output().find( "Cdrecord" ); + } + + if( pos < 0 ) + return false; + + pos = out.output().find( QRegExp("[0-9]"), pos ); + if( pos < 0 ) + return false; + + int endPos = out.output().find( QRegExp("\\s"), pos+1 ); + if( endPos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = path; + bin->version = out.output().mid( pos, endPos-pos ); + + if( wodim ) + bin->addFeature( "wodim" ); + + pos = out.output().find( "Copyright") + 14; + endPos = out.output().find( "\n", pos ); + + // cdrecord does not use local encoding for the copyright statement but plain latin1 + bin->copyright = QString::fromLatin1( out.output().mid( pos, endPos-pos ).local8Bit() ).stripWhiteSpace(); + } + else { + kdDebug() << "(K3bCdrecordProgram) could not start " << path << endl; + return false; + } + + if( !m_dvdPro && bin->version.suffix().endsWith( "-dvd" ) ) { + bin->addFeature( "dvd-patch" ); + bin->version = QString(bin->version.versionString()).remove("-dvd"); + } + + // probe features + KProcess fp; + out.setProcess( &fp ); + fp << path << "-help"; + if( fp.start( KProcess::Block, KProcess::AllOutput ) ) { + if( out.output().contains( "gracetime" ) ) + bin->addFeature( "gracetime" ); + if( out.output().contains( "-overburn" ) ) + bin->addFeature( "overburn" ); + if( out.output().contains( "-text" ) ) + bin->addFeature( "cdtext" ); + if( out.output().contains( "-clone" ) ) + bin->addFeature( "clone" ); + if( out.output().contains( "-tao" ) ) + bin->addFeature( "tao" ); + if( out.output().contains( "cuefile=" ) && + ( wodim || bin->version > K3bVersion( 2, 1, -1, "a14") ) ) // cuefile handling was still buggy in a14 + bin->addFeature( "cuefile" ); + + // new mode 2 options since cdrecord 2.01a12 + // we use both checks here since the help was not updated in 2.01a12 yet (well, I + // just double-checked and the help page is proper but there is no harm in having + // two checks) + // and the version check does not handle versions like 2.01-dvd properly + if( out.output().contains( "-xamix" ) || + bin->version >= K3bVersion( 2, 1, -1, "a12" ) || + wodim ) + bin->addFeature( "xamix" ); + + // check if we run cdrecord as root + struct stat s; + if( !::stat( QFile::encodeName(path), &s ) ) { + if( (s.st_mode & S_ISUID) && s.st_uid == 0 ) + bin->addFeature( "suidroot" ); + } + } + else { + kdDebug() << "(K3bCdrecordProgram) could not start " << bin->path << endl; + delete bin; + return false; + } + + if( bin->version < K3bVersion( 2, 0 ) && !wodim ) + bin->addFeature( "outdated" ); + + // FIXME: are these version correct? + if( bin->version >= K3bVersion("1.11a38") || wodim ) + bin->addFeature( "plain-atapi" ); + if( bin->version > K3bVersion("1.11a17") || wodim ) + bin->addFeature( "hacked-atapi" ); + + if( bin->version >= K3bVersion( 2, 1, 1, "a02" ) || wodim ) + bin->addFeature( "short-track-raw" ); + + if( bin->version >= K3bVersion( 2, 1, -1, "a13" ) || wodim ) + bin->addFeature( "audio-stdin" ); + + if( bin->version >= K3bVersion( "1.11a02" ) || wodim ) + bin->addFeature( "burnfree" ); + else + bin->addFeature( "burnproof" ); + + addBin( bin ); + return true; +} + + + +K3bMkisofsProgram::K3bMkisofsProgram() + : K3bExternalProgram( "mkisofs" ) +{ +} + +bool K3bMkisofsProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + bool genisoimage = false; + QString path = p; + QFileInfo fi( path ); + if( fi.isDir() ) { + if( path[path.length()-1] != '/' ) + path.append("/"); + + if( QFile::exists( path + "genisoimage" ) ) { + genisoimage = true; + path += "genisoimage"; + } + else if( QFile::exists( path + "mkisofs" ) ) { + path += "mkisofs"; + } + else + return false; + } + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + vp << path << "-version"; + K3bProcessOutputCollector out( &vp ); + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + int pos = -1; + if( genisoimage ) + pos = out.output().find( "genisoimage" ); + else + pos = out.output().find( "mkisofs" ); + + if( pos < 0 ) + return false; + + pos = out.output().find( QRegExp("[0-9]"), pos ); + if( pos < 0 ) + return false; + + int endPos = out.output().find( ' ', pos+1 ); + if( endPos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = path; + bin->version = out.output().mid( pos, endPos-pos ); + + if( genisoimage ) + bin->addFeature( "genisoimage" ); + } + else { + kdDebug() << "(K3bMkisofsProgram) could not start " << path << endl; + return false; + } + + + + // probe features + KProcess fp; + fp << path << "-help"; + out.setProcess( &fp ); + if( fp.start( KProcess::Block, KProcess::AllOutput ) ) { + if( out.output().contains( "-udf" ) ) + bin->addFeature( "udf" ); + if( out.output().contains( "-dvd-video" ) ) + bin->addFeature( "dvd-video" ); + if( out.output().contains( "-joliet-long" ) ) + bin->addFeature( "joliet-long" ); + if( out.output().contains( "-xa" ) ) + bin->addFeature( "xa" ); + if( out.output().contains( "-sectype" ) ) + bin->addFeature( "sectype" ); + + // check if we run mkisofs as root + struct stat s; + if( !::stat( QFile::encodeName(path), &s ) ) { + if( (s.st_mode & S_ISUID) && s.st_uid == 0 ) + bin->addFeature( "suidroot" ); + } + } + else { + kdDebug() << "(K3bMkisofsProgram) could not start " << bin->path << endl; + delete bin; + return false; + } + + if( bin->version < K3bVersion( 1, 14) && !genisoimage ) + bin->addFeature( "outdated" ); + + if( bin->version >= K3bVersion( 1, 15, -1, "a40" ) || genisoimage ) + bin->addFeature( "backslashed_filenames" ); + + if ( genisoimage && bin->version >= K3bVersion( 1, 1, 4 ) ) + bin->addFeature( "no-4gb-limit" ); + + if ( !genisoimage && bin->version >= K3bVersion( 2, 1, 1, "a32" ) ) + bin->addFeature( "no-4gb-limit" ); + + addBin(bin); + return true; +} + + +K3bReadcdProgram::K3bReadcdProgram() + : K3bExternalProgram( "readcd" ) +{ +} + +bool K3bReadcdProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + bool readom = false; + QString path = p; + QFileInfo fi( path ); + if( fi.isDir() ) { + if( path[path.length()-1] != '/' ) + path.append("/"); + + if( QFile::exists( path + "readom" ) ) { + readom = true; + path += "readom"; + } + else if( QFile::exists( path + "readcd" ) ) { + path += "readcd"; + } + else + return false; + } + + if( !QFile::exists( path ) ) + return false; + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + vp << path << "-version"; + K3bProcessOutputCollector out( &vp ); + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + int pos = -1; + if( readom ) + pos = out.output().find( "readom" ); + else + pos = out.output().find( "readcd" ); + if( pos < 0 ) + return false; + + pos = out.output().find( QRegExp("[0-9]"), pos ); + if( pos < 0 ) + return false; + + int endPos = out.output().find( ' ', pos+1 ); + if( endPos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = path; + bin->version = out.output().mid( pos, endPos-pos ); + + if( readom ) + bin->addFeature( "readom" ); + } + else { + kdDebug() << "(K3bMkisofsProgram) could not start " << path << endl; + return false; + } + + + + // probe features + KProcess fp; + fp << path << "-help"; + out.setProcess( &fp ); + if( fp.start( KProcess::Block, KProcess::AllOutput ) ) { + if( out.output().contains( "-clone" ) ) + bin->addFeature( "clone" ); + + // check if we run mkisofs as root + struct stat s; + if( !::stat( QFile::encodeName(path), &s ) ) { + if( (s.st_mode & S_ISUID) && s.st_uid == 0 ) + bin->addFeature( "suidroot" ); + } + } + else { + kdDebug() << "(K3bReadcdProgram) could not start " << bin->path << endl; + delete bin; + return false; + } + + + // FIXME: are these version correct? + if( bin->version >= K3bVersion("1.11a38") || readom ) + bin->addFeature( "plain-atapi" ); + if( bin->version > K3bVersion("1.11a17") || readom ) + bin->addFeature( "hacked-atapi" ); + + addBin(bin); + return true; +} + + +K3bCdrdaoProgram::K3bCdrdaoProgram() + : K3bExternalProgram( "cdrdao" ) +{ +} + +bool K3bCdrdaoProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + QString path = p; + QFileInfo fi( path ); + if( fi.isDir() ) { + if( path[path.length()-1] != '/' ) + path.append("/"); + path.append("cdrdao"); + } + + if( !QFile::exists( path ) ) + return false; + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + vp << path ; + K3bProcessOutputCollector out( &vp ); + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + int pos = out.output().find( "Cdrdao version" ); + if( pos < 0 ) + return false; + + pos = out.output().find( QRegExp("[0-9]"), pos ); + if( pos < 0 ) + return false; + + int endPos = out.output().find( ' ', pos+1 ); + if( endPos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = path; + bin->version = out.output().mid( pos, endPos-pos ); + + pos = out.output().find( "(C)", endPos+1 ) + 4; + endPos = out.output().find( '\n', pos ); + bin->copyright = out.output().mid( pos, endPos-pos ); + } + else { + kdDebug() << "(K3bCdrdaoProgram) could not start " << path << endl; + return false; + } + + + + // probe features + KProcess fp; + fp << path << "write" << "-h"; + out.setProcess( &fp ); + if( fp.start( KProcess::Block, KProcess::AllOutput ) ) { + if( out.output().contains( "--overburn" ) ) + bin->addFeature( "overburn" ); + if( out.output().contains( "--multi" ) ) + bin->addFeature( "multisession" ); + + if( out.output().contains( "--buffer-under-run-protection" ) ) + bin->addFeature( "disable-burnproof" ); + + // check if we run cdrdao as root + struct stat s; + if( !::stat( QFile::encodeName(path), &s ) ) { + if( (s.st_mode & S_ISUID) && s.st_uid == 0 ) + bin->addFeature( "suidroot" ); + } + } + else { + kdDebug() << "(K3bCdrdaoProgram) could not start " << bin->path << endl; + delete bin; + return false; + } + + + // SuSE 9.0 ships with a patched cdrdao 1.1.7 which contains an updated libschily + // Gentoo ships with a patched cdrdao 1.1.7 which contains scglib support + if( bin->version > K3bVersion( 1, 1, 7 ) || + bin->version == K3bVersion( 1, 1, 7, "-gentoo" ) || + bin->version == K3bVersion( 1, 1, 7, "-suse" ) ) { + // bin->addFeature( "plain-atapi" ); + bin->addFeature( "hacked-atapi" ); + } + + if( bin->version >= K3bVersion( 1, 1, 8 ) ) + bin->addFeature( "plain-atapi" ); + + addBin(bin); + return true; +} + + +K3bTranscodeProgram::K3bTranscodeProgram( const QString& transcodeProgram ) + : K3bExternalProgram( transcodeProgram ), + m_transcodeProgram( transcodeProgram ) +{ +} + +bool K3bTranscodeProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + QString path = p; + if( path[path.length()-1] != '/' ) + path.append("/"); + + QString appPath = path + m_transcodeProgram; + + if( !QFile::exists( appPath ) ) + return false; + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + vp << appPath << "-v"; + K3bProcessOutputCollector out( &vp ); + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + int pos = out.output().find( "transcode v" ); + if( pos < 0 ) + return false; + + pos += 11; + + int endPos = out.output().find( QRegExp("[\\s\\)]"), pos+1 ); + if( endPos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = appPath; + bin->version = out.output().mid( pos, endPos-pos ); + } + else { + kdDebug() << "(K3bTranscodeProgram) could not start " << appPath << endl; + return false; + } + + // + // Check features + // + QString modInfoBin = path + "tcmodinfo"; + KProcess modp; + modp << modInfoBin << "-p"; + out.setProcess( &modp ); + if( modp.start( KProcess::Block, KProcess::AllOutput ) ) { + QString modPath = out.output().stripWhiteSpace(); + QDir modDir( modPath ); + if( !modDir.entryList( "*export_xvid*", QDir::Files ).isEmpty() ) + bin->addFeature( "xvid" ); + if( !modDir.entryList( "*export_lame*", QDir::Files ).isEmpty() ) + bin->addFeature( "lame" ); + if( !modDir.entryList( "*export_ffmpeg*", QDir::Files ).isEmpty() ) + bin->addFeature( "ffmpeg" ); + if( !modDir.entryList( "*export_ac3*", QDir::Files ).isEmpty() ) + bin->addFeature( "ac3" ); + } + + addBin(bin); + return true; +} + + + +K3bVcdbuilderProgram::K3bVcdbuilderProgram( const QString& p ) + : K3bExternalProgram( p ), + m_vcdbuilderProgram( p ) +{ +} + +bool K3bVcdbuilderProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + QString path = p; + QFileInfo fi( path ); + if( fi.isDir() ) { + if( path[path.length()-1] != '/' ) + path.append("/"); + path.append(m_vcdbuilderProgram); + } + + if( !QFile::exists( path ) ) + return false; + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + vp << path << "-V"; + K3bProcessOutputCollector out( &vp ); + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + int pos = out.output().find( "GNU VCDImager" ); + if( pos < 0 ) + return false; + + pos += 14; + + int endPos = out.output().find( QRegExp("[\\n\\)]"), pos+1 ); + if( endPos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = path; + bin->version = out.output().mid( pos, endPos-pos ).stripWhiteSpace(); + + pos = out.output().find( "Copyright" ) + 14; + endPos = out.output().find( "\n", pos ); + bin->copyright = out.output().mid( pos, endPos-pos ).stripWhiteSpace(); + } + else { + kdDebug() << "(K3bVcdbuilderProgram) could not start " << path << endl; + return false; + } + + addBin(bin); + return true; +} + + +K3bNormalizeProgram::K3bNormalizeProgram() + : K3bExternalProgram( "normalize-audio" ) +{ +} + + +bool K3bNormalizeProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + QString path = p; + QFileInfo fi( path ); + if( fi.isDir() ) { + if( path[path.length()-1] != '/' ) + path.append("/"); + path.append("normalize-audio"); + } + + if( !QFile::exists( path ) ) + return false; + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + K3bProcessOutputCollector out( &vp ); + + vp << path << "--version"; + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + int pos = out.output().find( "normalize" ); + if( pos < 0 ) + return false; + + pos = out.output().find( QRegExp("\\d"), pos ); + if( pos < 0 ) + return false; + + int endPos = out.output().find( QRegExp("\\s"), pos+1 ); + if( endPos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = path; + bin->version = out.output().mid( pos, endPos-pos ); + + pos = out.output().find( "Copyright" )+14; + endPos = out.output().find( "\n", pos ); + bin->copyright = out.output().mid( pos, endPos-pos ).stripWhiteSpace(); + } + else { + kdDebug() << "(K3bCdrecordProgram) could not start " << path << endl; + return false; + } + + addBin( bin ); + return true; +} + + +K3bGrowisofsProgram::K3bGrowisofsProgram() + : K3bExternalProgram( "growisofs" ) +{ +} + +bool K3bGrowisofsProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + QString path = p; + QFileInfo fi( path ); + if( fi.isDir() ) { + if( path[path.length()-1] != '/' ) + path.append("/"); + path.append("growisofs"); + } + + if( !QFile::exists( path ) ) + return false; + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + K3bProcessOutputCollector out( &vp ); + + vp << path << "-version"; + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + int pos = out.output().find( "growisofs" ); + if( pos < 0 ) + return false; + + pos = out.output().find( QRegExp("\\d"), pos ); + if( pos < 0 ) + return false; + + int endPos = out.output().find( ",", pos+1 ); + if( endPos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = path; + bin->version = out.output().mid( pos, endPos-pos ); + } + else { + kdDebug() << "(K3bGrowisofsProgram) could not start " << path << endl; + return false; + } + + // fixed Copyright: + bin->copyright = "Andy Polyakov "; + + // check if we run growisofs as root + struct stat s; + if( !::stat( QFile::encodeName(path), &s ) ) { + if( (s.st_mode & S_ISUID) && s.st_uid == 0 ) + bin->addFeature( "suidroot" ); + } + + addBin( bin ); + return true; +} + + +K3bDvdformatProgram::K3bDvdformatProgram() + : K3bExternalProgram( "dvd+rw-format" ) +{ +} + +bool K3bDvdformatProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + QString path = p; + QFileInfo fi( path ); + if( fi.isDir() ) { + if( path[path.length()-1] != '/' ) + path.append("/"); + path.append("dvd+rw-format"); + } + + if( !QFile::exists( path ) ) + return false; + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + K3bProcessOutputCollector out( &vp ); + + vp << path; + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + // different locales make searching for the +- char difficult + // so we simply ignore it. + int pos = out.output().find( QRegExp("DVD.*RAM format utility") ); + if( pos < 0 ) + return false; + + pos = out.output().find( "version", pos ); + if( pos < 0 ) + return false; + + pos += 8; + + // the version ends in a dot. + int endPos = out.output().find( QRegExp("\\.\\D"), pos ); + if( endPos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = path; + bin->version = out.output().mid( pos, endPos-pos ); + } + else { + kdDebug() << "(K3bDvdformatProgram) could not start " << path << endl; + return false; + } + + // fixed Copyright: + bin->copyright = "Andy Polyakov "; + + // check if we run dvd+rw-format as root + struct stat s; + if( !::stat( QFile::encodeName(path), &s ) ) { + if( (s.st_mode & S_ISUID) && s.st_uid == 0 ) + bin->addFeature( "suidroot" ); + } + + addBin( bin ); + return true; +} + + +K3bDvdBooktypeProgram::K3bDvdBooktypeProgram() + : K3bExternalProgram( "dvd+rw-booktype" ) +{ +} + +bool K3bDvdBooktypeProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + QString path = p; + QFileInfo fi( path ); + if( fi.isDir() ) { + if( path[path.length()-1] != '/' ) + path.append("/"); + path.append("dvd+rw-booktype"); + } + + if( !QFile::exists( path ) ) + return false; + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + K3bProcessOutputCollector out( &vp ); + + vp << path; + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + int pos = out.output().find( "dvd+rw-booktype" ); + if( pos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = path; + // No version information. Create dummy version + bin->version = K3bVersion( 1, 0, 0 ); + } + else { + kdDebug() << "(K3bDvdBooktypeProgram) could not start " << path << endl; + return false; + } + + addBin( bin ); + return true; +} + + + +K3bCdda2wavProgram::K3bCdda2wavProgram() + : K3bExternalProgram( "cdda2wav" ) +{ +} + +bool K3bCdda2wavProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + QString path = p; + QFileInfo fi( path ); + if( fi.isDir() ) { + if( path[path.length()-1] != '/' ) + path.append("/"); + path.append("cdda2wav"); + } + + if( !QFile::exists( path ) ) + return false; + + K3bExternalBin* bin = 0; + + // probe version + KProcess vp; + K3bProcessOutputCollector out( &vp ); + + vp << path << "-h"; + if( vp.start( KProcess::Block, KProcess::AllOutput ) ) { + int pos = out.output().find( "cdda2wav" ); + if( pos < 0 ) + return false; + + pos = out.output().find( "Version", pos ); + if( pos < 0 ) + return false; + + pos += 8; + + // the version does not end in a space but the kernel info + int endPos = out.output().find( QRegExp("[^\\d\\.]"), pos ); + if( endPos < 0 ) + return false; + + bin = new K3bExternalBin( this ); + bin->path = path; + bin->version = out.output().mid( pos, endPos-pos ); + + // features (we do this since the cdda2wav help says that the short + // options will disappear soon) + if( out.output().find( "-info-only" ) ) + bin->addFeature( "info-only" ); // otherwise use the -J option + if( out.output().find( "-no-infofile" ) ) + bin->addFeature( "no-infofile" ); // otherwise use the -H option + if( out.output().find( "-gui" ) ) + bin->addFeature( "gui" ); // otherwise use the -g option + if( out.output().find( "-bulk" ) ) + bin->addFeature( "bulk" ); // otherwise use the -B option + if( out.output().find( "dev=" ) ) + bin->addFeature( "dev" ); // otherwise use the -B option + } + else { + kdDebug() << "(K3bCdda2wavProgram) could not start " << path << endl; + return false; + } + + // check if we run as root + struct stat s; + if( !::stat( QFile::encodeName(path), &s ) ) { + if( (s.st_mode & S_ISUID) && s.st_uid == 0 ) + bin->addFeature( "suidroot" ); + } + + addBin( bin ); + return true; +} + diff --git a/libk3b/core/k3bdefaultexternalprograms.h b/libk3b/core/k3bdefaultexternalprograms.h new file mode 100644 index 0000000..3212727 --- /dev/null +++ b/libk3b/core/k3bdefaultexternalprograms.h @@ -0,0 +1,143 @@ +/* + * + * $Id: k3bdefaultexternalprograms.h 623768 2007-01-15 13:33:55Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#ifndef _K3B_DEFAULT_EXTERNAL_BIN_PROGRAMS_H_ +#define _K3B_DEFAULT_EXTERNAL_BIN_PROGRAMS_H_ + +#include "k3bexternalbinmanager.h" +#include "k3b_export.h" +class K3bExternalBinManager; + +namespace K3b +{ + LIBK3B_EXPORT void addDefaultPrograms( K3bExternalBinManager* ); + LIBK3B_EXPORT void addTranscodePrograms( K3bExternalBinManager* ); + LIBK3B_EXPORT void addVcdimagerPrograms( K3bExternalBinManager* ); +} + + +class LIBK3B_EXPORT K3bCdrecordProgram : public K3bExternalProgram +{ + public: + K3bCdrecordProgram( bool dvdPro ); + + bool scan( const QString& ); + + private: + bool m_dvdPro; +}; + + +class LIBK3B_EXPORT K3bMkisofsProgram : public K3bExternalProgram +{ + public: + K3bMkisofsProgram(); + + bool scan( const QString& ); +}; + + +class LIBK3B_EXPORT K3bReadcdProgram : public K3bExternalProgram +{ + public: + K3bReadcdProgram(); + + bool scan( const QString& ); +}; + + +class LIBK3B_EXPORT K3bCdrdaoProgram : public K3bExternalProgram +{ + public: + K3bCdrdaoProgram(); + + bool scan( const QString& ); +}; + + +class LIBK3B_EXPORT K3bTranscodeProgram : public K3bExternalProgram +{ + public: + K3bTranscodeProgram( const QString& transcodeProgram ); + + bool scan( const QString& ); + + // no user parameters (yet) + bool supportsUserParameters() const { return false; } + + private: + QString m_transcodeProgram; +}; + + +class LIBK3B_EXPORT K3bVcdbuilderProgram : public K3bExternalProgram +{ + public: + K3bVcdbuilderProgram( const QString& ); + + bool scan( const QString& ); + + private: + QString m_vcdbuilderProgram; +}; + + +class LIBK3B_EXPORT K3bNormalizeProgram : public K3bExternalProgram +{ + public: + K3bNormalizeProgram(); + + bool scan( const QString& ); +}; + + +class LIBK3B_EXPORT K3bGrowisofsProgram : public K3bExternalProgram +{ + public: + K3bGrowisofsProgram(); + + bool scan( const QString& ); +}; + + +class LIBK3B_EXPORT K3bDvdformatProgram : public K3bExternalProgram +{ + public: + K3bDvdformatProgram(); + + bool scan( const QString& ); +}; + + +class LIBK3B_EXPORT K3bDvdBooktypeProgram : public K3bExternalProgram +{ + public: + K3bDvdBooktypeProgram(); + + bool scan( const QString& ); +}; + + +class LIBK3B_EXPORT K3bCdda2wavProgram : public K3bExternalProgram +{ + public: + K3bCdda2wavProgram(); + + bool scan( const QString& ); +}; + +#endif diff --git a/libk3b/core/k3bexternalbinmanager.cpp b/libk3b/core/k3bexternalbinmanager.cpp new file mode 100644 index 0000000..2b21a85 --- /dev/null +++ b/libk3b/core/k3bexternalbinmanager.cpp @@ -0,0 +1,389 @@ +/* + * + * $Id: k3bexternalbinmanager.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bexternalbinmanager.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + + + +QString K3bExternalBinManager::m_noPath = ""; + + +// /////////////////////////////////////////////////////////// +// +// K3BEXTERNALBIN +// +// /////////////////////////////////////////////////////////// + +K3bExternalBin::K3bExternalBin( K3bExternalProgram* p ) + : m_program(p) +{ +} + + +bool K3bExternalBin::isEmpty() const +{ + return !version.isValid(); +} + + +const QString& K3bExternalBin::name() const +{ + return m_program->name(); +} + + +bool K3bExternalBin::hasFeature( const QString& f ) const +{ + return m_features.contains( f ); +} + + +void K3bExternalBin::addFeature( const QString& f ) +{ + m_features.append( f ); +} + + +const QStringList& K3bExternalBin::userParameters() const +{ + return m_program->userParameters(); +} + + + +// /////////////////////////////////////////////////////////// +// +// K3BEXTERNALPROGRAM +// +// /////////////////////////////////////////////////////////// + + +K3bExternalProgram::K3bExternalProgram( const QString& name ) + : m_name( name ) +{ + m_bins.setAutoDelete( true ); +} + + +K3bExternalProgram::~K3bExternalProgram() +{ +} + + +const K3bExternalBin* K3bExternalProgram::mostRecentBin() const +{ + QPtrListIterator it( m_bins ); + K3bExternalBin* bin = *it; + ++it; + while( *it ) { + if( it.current()->version > bin->version ) + bin = *it; + ++it; + } + return bin; +} + + +void K3bExternalProgram::addBin( K3bExternalBin* bin ) +{ + if( !m_bins.contains( bin ) ) { + // insertion sort + // the first bin in the list is always the one used + // so we default to using the newest one + K3bExternalBin* oldBin = m_bins.first(); + while( oldBin && oldBin->version > bin->version ) + oldBin = m_bins.next(); + + m_bins.insert( oldBin ? m_bins.at() : m_bins.count(), bin ); + } +} + +void K3bExternalProgram::setDefault( const K3bExternalBin* bin ) +{ + if( m_bins.contains( bin ) ) + m_bins.take( m_bins.find( bin ) ); + + // the first bin in the list is always the one used + m_bins.insert( 0, bin ); +} + + +void K3bExternalProgram::setDefault( const QString& path ) +{ + for( QPtrListIterator it( m_bins ); it.current(); ++it ) { + if( it.current()->path == path ) { + setDefault( it.current() ); + return; + } + } +} + + +void K3bExternalProgram::addUserParameter( const QString& p ) +{ + if( !m_userParameters.contains( p ) ) + m_userParameters.append(p); +} + + + +// /////////////////////////////////////////////////////////// +// +// K3BEXTERNALBINMANAGER +// +// /////////////////////////////////////////////////////////// + + +K3bExternalBinManager::K3bExternalBinManager( QObject* parent, const char* name ) + : QObject( parent, name ) +{ +} + + +K3bExternalBinManager::~K3bExternalBinManager() +{ + clear(); +} + + +bool K3bExternalBinManager::readConfig( KConfig* c ) +{ + loadDefaultSearchPath(); + + c->setGroup( "External Programs" ); + + if( c->hasKey( "search path" ) ) + setSearchPath( c->readPathListEntry( "search path" ) ); + + search(); + + for ( QMap::iterator it = m_programs.begin(); it != m_programs.end(); ++it ) { + K3bExternalProgram* p = it.data(); + if( c->hasKey( p->name() + " default" ) ) { + p->setDefault( c->readEntry( p->name() + " default" ) ); + } + if( c->hasKey( p->name() + " user parameters" ) ) { + QStringList list = c->readListEntry( p->name() + " user parameters" ); + for( QStringList::iterator strIt = list.begin(); strIt != list.end(); ++strIt ) + p->addUserParameter( *strIt ); + } + if( c->hasKey( p->name() + " last seen newest version" ) ) { + K3bVersion lastMax( c->readEntry( p->name() + " last seen newest version" ) ); + // now search for a newer version and use it (because it was installed after the last + // K3b run and most users would probably expect K3b to use a newly installed version) + const K3bExternalBin* newestBin = p->mostRecentBin(); + if( newestBin && newestBin->version > lastMax ) + p->setDefault( newestBin ); + } + } + + return true; +} + +bool K3bExternalBinManager::saveConfig( KConfig* c ) +{ + c->setGroup( "External Programs" ); + c->writePathEntry( "search path", m_searchPath ); + + for ( QMap::iterator it = m_programs.begin(); it != m_programs.end(); ++it ) { + K3bExternalProgram* p = it.data(); + if( p->defaultBin() ) + c->writeEntry( p->name() + " default", p->defaultBin()->path ); + + c->writeEntry( p->name() + " user parameters", p->userParameters() ); + + const K3bExternalBin* newestBin = p->mostRecentBin(); + if( newestBin ) + c->writeEntry( p->name() + " last seen newest version", newestBin->version ); + } + + return true; +} + + +bool K3bExternalBinManager::foundBin( const QString& name ) +{ + if( m_programs.find( name ) == m_programs.end() ) + return false; + else + return (m_programs[name]->defaultBin() != 0); +} + + +const QString& K3bExternalBinManager::binPath( const QString& name ) +{ + if( m_programs.find( name ) == m_programs.end() ) + return m_noPath; + + if( m_programs[name]->defaultBin() != 0 ) + return m_programs[name]->defaultBin()->path; + else + return m_noPath; +} + + +const K3bExternalBin* K3bExternalBinManager::binObject( const QString& name ) +{ + if( m_programs.find( name ) == m_programs.end() ) + return 0; + + return m_programs[name]->defaultBin(); +} + + +void K3bExternalBinManager::addProgram( K3bExternalProgram* p ) +{ + m_programs.insert( p->name(), p ); +} + + +void K3bExternalBinManager::clear() +{ + for( QMap::Iterator it = m_programs.begin(); it != m_programs.end(); ++it ) + delete it.data(); + m_programs.clear(); +} + + +void K3bExternalBinManager::search() +{ + if( m_searchPath.isEmpty() ) + loadDefaultSearchPath(); + + for( QMap::iterator it = m_programs.begin(); it != m_programs.end(); ++it ) { + it.data()->clear(); + } + + // do not search one path twice + QStringList paths; + for( QStringList::const_iterator it = m_searchPath.begin(); it != m_searchPath.end(); ++it ) { + QString p = *it; + if( p[p.length()-1] == '/' ) + p.truncate( p.length()-1 ); + if( !paths.contains( p ) && !paths.contains( p + "/" ) ) + paths.append(p); + } + + // get the environment path variable + char* env_path = ::getenv("PATH"); + if( env_path ) { + QStringList env_pathList = QStringList::split(":", QString::fromLocal8Bit(env_path)); + for( QStringList::const_iterator it = env_pathList.begin(); it != env_pathList.end(); ++it ) { + QString p = *it; + if( p[p.length()-1] == '/' ) + p.truncate( p.length()-1 ); + if( !paths.contains( p ) && !paths.contains( p + "/" ) ) + paths.append(p); + } + } + + + for( QStringList::const_iterator it = paths.begin(); it != paths.end(); ++it ) + for( QMap::iterator pit = m_programs.begin(); pit != m_programs.end(); ++pit ) + pit.data()->scan(*it); + + // TESTING + // ///////////////////////// + const K3bExternalBin* bin = program("cdrecord")->defaultBin(); + + if( !bin ) { + kdDebug() << "(K3bExternalBinManager) Probing cdrecord failed" << endl; + } + else { + kdDebug() << "(K3bExternalBinManager) Cdrecord " << bin->version << " features: " + << bin->features().join( ", " ) << endl; + + if( bin->version >= K3bVersion("1.11a02") ) + kdDebug() << "(K3bExternalBinManager) " + << bin->version.majorVersion() << " " << bin->version.minorVersion() << " " << bin->version.patchLevel() + << " " << bin->version.suffix() + << " seems to be cdrecord version >= 1.11a02, using burnfree instead of burnproof" << endl; + if( bin->version >= K3bVersion("1.11a31") ) + kdDebug() << "(K3bExternalBinManager) seems to be cdrecord version >= 1.11a31, support for Just Link via burnfree " + << "driveroption" << endl; + } +} + + +K3bExternalProgram* K3bExternalBinManager::program( const QString& name ) const +{ + if( m_programs.find( name ) == m_programs.end() ) + return 0; + else + return m_programs[name]; +} + + +void K3bExternalBinManager::loadDefaultSearchPath() +{ + static const char* defaultSearchPaths[] = { "/usr/bin/", + "/usr/local/bin/", + "/usr/sbin/", + "/usr/local/sbin/", + "/opt/schily/bin/", + "/sbin", + 0 }; + + m_searchPath.clear(); + for( int i = 0; defaultSearchPaths[i]; ++i ) { + m_searchPath.append( defaultSearchPaths[i] ); + } +} + + +void K3bExternalBinManager::setSearchPath( const QStringList& list ) +{ + loadDefaultSearchPath(); + + for( QStringList::const_iterator it = list.begin(); it != list.end(); ++it ) { + if( !m_searchPath.contains( *it ) ) + m_searchPath.append( *it ); + } +} + + +void K3bExternalBinManager::addSearchPath( const QString& path ) +{ + if( !m_searchPath.contains( path ) ) + m_searchPath.append( path ); +} + + + +const K3bExternalBin* K3bExternalBinManager::mostRecentBinObject( const QString& name ) +{ + if( K3bExternalProgram* p = program( name ) ) + return p->mostRecentBin(); + else + return 0; +} + +#include "k3bexternalbinmanager.moc" + diff --git a/libk3b/core/k3bexternalbinmanager.h b/libk3b/core/k3bexternalbinmanager.h new file mode 100644 index 0000000..e7fe601 --- /dev/null +++ b/libk3b/core/k3bexternalbinmanager.h @@ -0,0 +1,162 @@ +/* + * + * $Id: k3bexternalbinmanager.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_EXTERNAL_BIN_MANAGER_H +#define K3B_EXTERNAL_BIN_MANAGER_H + +#include +#include +#include +#include +#include +#include "k3b_export.h" +#include "k3bversion.h" + +class KConfig; +class KProcess; + + +class K3bExternalProgram; + + +/** + * A K3bExternalBin represents an installed version of a program. + * All K3bExternalBin objects are managed by K3bExternalPrograms. + * + * A bin may have certain features that are represented by a string. + */ +class LIBK3B_EXPORT K3bExternalBin +{ + public: + K3bExternalBin( K3bExternalProgram* ); + virtual ~K3bExternalBin() {} + + K3bVersion version; + QString path; + QString copyright; + + const QString& name() const; + bool isEmpty() const; + const QStringList& userParameters() const; + const QStringList& features() const { return m_features; } + + bool hasFeature( const QString& ) const; + void addFeature( const QString& ); + + K3bExternalProgram* program() const { return m_program; } + + private: + QStringList m_features; + K3bExternalProgram* m_program; +}; + + +/** + * This is the main class that represents a program + * It's scan method has to be reimplemented for every program + * It manages a list of K3bExternalBin-objects that each represent + * one installed version of the program. + */ +class LIBK3B_EXPORT K3bExternalProgram +{ + public: + K3bExternalProgram( const QString& name ); + virtual ~K3bExternalProgram(); + + const K3bExternalBin* defaultBin() const { return m_bins.getFirst(); } + const K3bExternalBin* mostRecentBin() const; + + void addUserParameter( const QString& ); + void setUserParameters( const QStringList& list ) { m_userParameters = list; } + + const QStringList& userParameters() const { return m_userParameters; } + const QString& name() const { return m_name; } + + void addBin( K3bExternalBin* ); + void clear() { m_bins.clear(); } + void setDefault( const K3bExternalBin* ); + void setDefault( const QString& path ); + + const QPtrList& bins() const { return m_bins; } + + /** + * this scans for the program in the given path, + * adds the found bin object to the list and returnes true. + * if nothing could be found false is returned. + */ + virtual bool scan( const QString& ) {return false;}//= 0; + + /** + * reimplement this if it does not make sense to have the user be able + * to specify additional parameters + */ + virtual bool supportsUserParameters() const { return true; } + + private: + QString m_name; + QStringList m_userParameters; + QPtrList m_bins; +}; + + +class LIBK3B_EXPORT K3bExternalBinManager : public QObject +{ + Q_OBJECT + + public: + K3bExternalBinManager( QObject* parent = 0, const char* name = 0 ); + ~K3bExternalBinManager(); + + void search(); + + /** + * read config and add changes to current map. + * Takes care of setting the config group + */ + bool readConfig( KConfig* ); + + /** + * Takes care of setting the config group + */ + bool saveConfig( KConfig* ); + + bool foundBin( const QString& name ); + const QString& binPath( const QString& name ); + const K3bExternalBin* binObject( const QString& name ); + const K3bExternalBin* mostRecentBinObject( const QString& name ); + + K3bExternalProgram* program( const QString& ) const; + const QMap& programs() const { return m_programs; } + + /** always extends the default searchpath */ + void setSearchPath( const QStringList& ); + void addSearchPath( const QString& ); + void loadDefaultSearchPath(); + + const QStringList& searchPath() const { return m_searchPath; } + + void addProgram( K3bExternalProgram* ); + void clear(); + + private: + QMap m_programs; + QStringList m_searchPath; + + static QString m_noPath; // used for binPath() to return const string + + QString m_gatheredOutput; +}; + +#endif diff --git a/libk3b/core/k3bglobals.cpp b/libk3b/core/k3bglobals.cpp new file mode 100644 index 0000000..fc5a4e1 --- /dev/null +++ b/libk3b/core/k3bglobals.cpp @@ -0,0 +1,634 @@ +/* + * + * $Id: k3bglobals.cpp 659634 2007-04-30 14:51:32Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include + + +#include "k3bglobals.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#if defined(__FreeBSD__) || defined(__NetBSD__) +# include +# include +# include +# define bswap_16(x) bswap16(x) +# define bswap_32(x) bswap32(x) +# define bswap_64(x) bswap64(x) +#else +# include +#endif +#ifdef HAVE_SYS_STATVFS_H +# include +#endif +#ifdef HAVE_SYS_VFS_H +# include +#endif + + +/* +struct Sample { + unsigned char msbLeft; + unsigned char lsbLeft; + unsigned char msbRight; + unsigned char lsbRight; + + short left() const { + return ( msbLeft << 8 ) | lsbLeft; + } + short right() const { + return ( msbRight << 8 ) | lsbRight; + } + void left( short d ) { + msbLeft = d >> 8; + lsbLeft = d; + } + void right( short d ) { + msbRight = d >> 8; + lsbRight = d; + } +}; +*/ + +QString K3b::framesToString( int h, bool showFrames ) +{ + int m = h / 4500; + int s = (h % 4500) / 75; + int f = h % 75; + + QString str; + + if( showFrames ) { + // cdrdao needs the MSF format where 1 second has 75 frames! + str.sprintf( "%.2i:%.2i:%.2i", m, s, f ); + } + else + str.sprintf( "%.2i:%.2i", m, s ); + + return str; +} + +/*QString K3b::sizeToTime(long size) +{ + int h = size / sizeof(Sample) / 588; + return framesToString(h, false); +}*/ + + +Q_INT16 K3b::swapByteOrder( const Q_INT16& i ) +{ + return bswap_16( i ); + //((i << 8) & 0xff00) | ((i >> 8 ) & 0xff); +} + + +Q_INT32 K3b::swapByteOrder( const Q_INT32& i ) +{ + //return ((i << 24) & 0xff000000) | ((i << 8) & 0xff0000) | ((i >> 8) & 0xff00) | ((i >> 24) & 0xff ); + return bswap_32( i ); +} + + +Q_INT64 K3b::swapByteOrder( const Q_INT64& i ) +{ + return bswap_64( i ); +} + + +int K3b::round( double d ) +{ + return (int)( floor(d) + 0.5 <= d ? ceil(d) : floor(d) ); +} + + +QString K3b::findUniqueFilePrefix( const QString& _prefix, const QString& path ) +{ + QString url; + if( path.isEmpty() || !QFile::exists(path) ) + url = defaultTempPath(); + else + url = prepareDir( path ); + + QString prefix = _prefix; + if( prefix.isEmpty() ) + prefix = "k3b_"; + + // now create the unique prefix + QDir dir( url ); + QStringList entries = dir.entryList( QDir::DefaultFilter, QDir::Name ); + int i = 0; + for( QStringList::iterator it = entries.begin(); + it != entries.end(); ++it ) { + if( (*it).startsWith( prefix + QString::number(i) ) ) { + i++; + it = entries.begin(); + } + } + + return url + prefix + QString::number(i); +} + + +QString K3b::findTempFile( const QString& ending, const QString& d ) +{ + return findUniqueFilePrefix( "k3b_", d ) + ( ending.isEmpty() ? QString::null : (QString::fromLatin1(".") + ending) ); +} + + +QString K3b::defaultTempPath() +{ + QString oldGroup = kapp->config()->group(); + kapp->config()->setGroup( "General Options" ); + QString url = kapp->config()->readPathEntry( "Temp Dir", KGlobal::dirs()->resourceDirs( "tmp" ).first() ); + kapp->config()->setGroup( oldGroup ); + return prepareDir(url); +} + + +QString K3b::prepareDir( const QString& dir ) +{ + return (dir + (dir[dir.length()-1] != '/' ? "/" : "")); +} + + +QString K3b::parentDir( const QString& path ) +{ + QString parent = path; + if( path[path.length()-1] == '/' ) + parent.truncate( parent.length()-1 ); + + int pos = parent.findRev( '/' ); + if( pos >= 0 ) + parent.truncate( pos+1 ); + else // relative path, do anything... + parent = "/"; + + return parent; +} + + +QString K3b::fixupPath( const QString& path ) +{ + QString s; + bool lastWasSlash = false; + for( unsigned int i = 0; i < path.length(); ++i ) { + if( path[i] == '/' ) { + if( !lastWasSlash ) { + lastWasSlash = true; + s.append( "/" ); + } + } + else { + lastWasSlash = false; + s.append( path[i] ); + } + } + + return s; +} + + +K3bVersion K3b::kernelVersion() +{ + // initialize kernel version + K3bVersion v; + utsname unameinfo; + if( ::uname(&unameinfo) == 0 ) { + v = QString::fromLocal8Bit( unameinfo.release ); + kdDebug() << "kernel version: " << v << endl; + } + else + kdError() << "could not determine kernel version." << endl; + return v; +} + + +K3bVersion K3b::simpleKernelVersion() +{ + return kernelVersion().simplify(); +} + + +QString K3b::systemName() +{ + QString v; + utsname unameinfo; + if( ::uname(&unameinfo) == 0 ) { + v = QString::fromLocal8Bit( unameinfo.sysname ); + } + else + kdError() << "could not determine system name." << endl; + return v; +} + + +bool K3b::kbFreeOnFs( const QString& path, unsigned long& size, unsigned long& avail ) +{ + struct statvfs fs; + if( ::statvfs( QFile::encodeName(path), &fs ) == 0 ) { + unsigned long kBfak = fs.f_frsize/1024; + + size = fs.f_blocks*kBfak; + avail = fs.f_bavail*kBfak; + + return true; + } + else + return false; +} + + +KIO::filesize_t K3b::filesize( const KURL& url ) +{ + if( url.isLocalFile() ) { + k3b_struct_stat buf; + if ( !k3b_stat( QFile::encodeName( url.path() ), &buf ) ) { + return (KIO::filesize_t)buf.st_size; + } + } + + KIO::UDSEntry uds; + KIO::NetAccess::stat( url, uds, 0 ); + for( KIO::UDSEntry::const_iterator it = uds.begin(); it != uds.end(); ++it ) { + if( (*it).m_uds == KIO::UDS_SIZE ) { + return (*it).m_long; + } + } + + return ( KIO::filesize_t )0; +} + + +KIO::filesize_t K3b::imageFilesize( const KURL& url ) +{ + KIO::filesize_t size = K3b::filesize( url ); + int cnt = 0; + while( KIO::NetAccess::exists( KURL::fromPathOrURL( url.url() + '.' + QString::number(cnt).rightJustify( 3, '0' ) ), true ) ) + size += K3b::filesize( KURL::fromPathOrURL( url.url() + '.' + QString::number(cnt++).rightJustify( 3, '0' ) ) ); + return size; +} + + +QString K3b::cutFilename( const QString& name, unsigned int len ) +{ + if( name.length() > len ) { + QString ret = name; + + // determine extension (we think of an extension to be at most 5 chars in length) + int pos = name.find( '.', -6 ); + if( pos > 0 ) + len -= (name.length() - pos); + + ret.truncate( len ); + + if( pos > 0 ) + ret.append( name.mid( pos ) ); + + return ret; + } + else + return name; +} + + +QString K3b::removeFilenameExtension( const QString& name ) +{ + QString v = name; + int dotpos = v.findRev( '.' ); + if( dotpos > 0 ) + v.truncate( dotpos ); + return v; +} + + +QString K3b::appendNumberToFilename( const QString& name, int num, unsigned int maxlen ) +{ + // determine extension (we think of an extension to be at most 5 chars in length) + QString result = name; + QString ext; + int pos = name.find( '.', -6 ); + if( pos > 0 ) { + ext = name.mid(pos); + result.truncate( pos ); + } + + ext.prepend( QString::number(num) ); + result.truncate( maxlen - ext.length() ); + + return result + ext; +} + + +bool K3b::plainAtapiSupport() +{ + // FIXME: what about BSD? + return ( K3b::simpleKernelVersion() >= K3bVersion( 2, 5, 40 ) ); +} + + +bool K3b::hackedAtapiSupport() +{ + // IMPROVEME!!! + // FIXME: since when does the kernel support this? + return ( K3b::simpleKernelVersion() >= K3bVersion( 2, 4, 0 ) ); +} + + +QString K3b::externalBinDeviceParameter( K3bDevice::Device* dev, const K3bExternalBin* bin ) +{ +#ifdef Q_OS_LINUX + // + // experimental: always use block devices on 2.6 kernels + // + if( simpleKernelVersion() >= K3bVersion( 2, 6, 0 ) ) + return dev->blockDeviceName(); + else +#endif + if( dev->interfaceType() == K3bDevice::SCSI ) + return dev->busTargetLun(); + else if( (plainAtapiSupport() && bin->hasFeature("plain-atapi") ) ) + return dev->blockDeviceName(); + else + return QString("ATAPI:%1").arg(dev->blockDeviceName()); +} + + +int K3b::writingAppFromString( const QString& s ) +{ + if( s.lower() == "cdrdao" ) + return K3b::CDRDAO; + else if( s.lower() == "cdrecord" ) + return K3b::CDRECORD; + else if( s.lower() == "dvdrecord" ) + return K3b::DVDRECORD; + else if( s.lower() == "growisofs" ) + return K3b::GROWISOFS; + else if( s.lower() == "dvd+rw-format" ) + return K3b::DVD_RW_FORMAT; + else + return K3b::DEFAULT; +} + + +QString K3b::writingModeString( int mode ) +{ + if( mode == WRITING_MODE_AUTO ) + return i18n("Auto"); + else + return K3bDevice::writingModeString( mode ); +} + + +QString K3b::resolveLink( const QString& file ) +{ + QFileInfo f( file ); + QStringList steps( f.absFilePath() ); + while( f.isSymLink() ) { + QString p = f.readLink(); + if( !p.startsWith( "/" ) ) + p.prepend( f.dirPath(true) + "/" ); + f.setFile( p ); + if( steps.contains( f.absFilePath() ) ) { + kdDebug() << "(K3b) symlink loop detected." << endl; + break; + } + else + steps.append( f.absFilePath() ); + } + return f.absFilePath(); +} + + +K3bDevice::Device* K3b::urlToDevice( const KURL& deviceUrl ) +{ + if( deviceUrl.protocol() == "media" || deviceUrl.protocol() == "system" ) { + kdDebug() << "(K3b) Asking mediamanager for " << deviceUrl.fileName() << endl; + DCOPRef mediamanager("kded", "mediamanager"); + DCOPReply reply = mediamanager.call("properties(QString)", deviceUrl.fileName()); + QStringList properties = reply; + if( !reply.isValid() || properties.count() < 6 ) { + kdError() << "(K3b) Invalid reply from mediamanager" << endl; + return 0; + } + else { + kdDebug() << "(K3b) Reply from mediamanager " << properties[5] << endl; + return k3bcore->deviceManager()->findDevice( properties[5] ); + } + } + + return k3bcore->deviceManager()->findDevice( deviceUrl.path() ); +} + + +KURL K3b::convertToLocalUrl( const KURL& url ) +{ + if( !url.isLocalFile() ) { +#if KDE_IS_VERSION(3,4,91) + return KIO::NetAccess::mostLocalURL( url, 0 ); +#else +#ifndef UDS_LOCAL_PATH +#define UDS_LOCAL_PATH (72 | KIO::UDS_STRING) +#else + using namespace KIO; +#endif + KIO::UDSEntry e; + if( KIO::NetAccess::stat( url, e, 0 ) ) { + const KIO::UDSEntry::ConstIterator end = e.end(); + for( KIO::UDSEntry::ConstIterator it = e.begin(); it != end; ++it ) { + if( (*it).m_uds == UDS_LOCAL_PATH && !(*it).m_str.isEmpty() ) + return KURL::fromPathOrURL( (*it).m_str ); + } + } +#endif + } + + return url; +} + + +KURL::List K3b::convertToLocalUrls( const KURL::List& urls ) +{ + KURL::List r; + for( KURL::List::const_iterator it = urls.constBegin(); it != urls.constEnd(); ++it ) + r.append( convertToLocalUrl( *it ) ); + return r; +} + + +Q_INT16 K3b::fromLe16( char* data ) +{ +#ifdef WORDS_BIGENDIAN // __BYTE_ORDER == __BIG_ENDIAN + return swapByteOrder( *((Q_INT16*)data) ); +#else + return *((Q_INT16*)data); +#endif +} + + +Q_INT32 K3b::fromLe32( char* data ) +{ +#ifdef WORDS_BIGENDIAN // __BYTE_ORDER == __BIG_ENDIAN + return swapByteOrder( *((Q_INT32*)data) ); +#else + return *((Q_INT32*)data); +#endif +} + + +Q_INT64 K3b::fromLe64( char* data ) +{ +#ifdef WORDS_BIGENDIAN // __BYTE_ORDER == __BIG_ENDIAN + return swapByteOrder( *((Q_INT64*)data) ); +#else + return *((Q_INT64*)data); +#endif +} + + +QString K3b::findExe( const QString& name ) +{ + // first we search the path + QString bin = KStandardDirs::findExe( name ); + + // then go on with our own little list + if( bin.isEmpty() ) + bin = KStandardDirs::findExe( name, k3bcore->externalBinManager()->searchPath().join(":") ); + + return bin; +} + + +bool K3b::isMounted( K3bDevice::Device* dev ) +{ + if( !dev ) + return false; + + return !KIO::findDeviceMountPoint( dev->blockDeviceName() ).isEmpty(); +} + + +bool K3b::unmount( K3bDevice::Device* dev ) +{ + if( !dev ) + return false; + + QString mntDev = dev->blockDeviceName(); + +#if KDE_IS_VERSION(3,4,0) + // first try to unmount it the standard way + if( KIO::NetAccess::synchronousRun( KIO::unmount( mntDev, false ), 0 ) ) + return true; +#endif + + QString umountBin = K3b::findExe( "umount" ); + if( !umountBin.isEmpty() ) { + KProcess p; + p << umountBin; + p << "-l"; // lazy unmount + p << dev->blockDeviceName(); + p.start( KProcess::Block ); + if( !p.exitStatus() ) + return true; + } + + // now try pmount + QString pumountBin = K3b::findExe( "pumount" ); + if( !pumountBin.isEmpty() ) { + KProcess p; + p << pumountBin; + p << "-l"; // lazy unmount + p << dev->blockDeviceName(); + p.start( KProcess::Block ); + return !p.exitStatus(); + } + else { +#ifdef HAVE_HAL + return !K3bDevice::HalConnection::instance()->unmount( dev ); +#else + return false; +#endif + } +} + + +bool K3b::mount( K3bDevice::Device* dev ) +{ + if( !dev ) + return false; + + QString mntDev = dev->blockDeviceName(); + +#if KDE_IS_VERSION(3,4,0) + // first try to mount it the standard way + if( KIO::NetAccess::synchronousRun( KIO::mount( true, 0, mntDev, false ), 0 ) ) + return true; +#endif + +#ifdef HAVE_HAL + if( !K3bDevice::HalConnection::instance()->mount( dev ) ) + return true; +#endif + + // now try pmount + QString pmountBin = K3b::findExe( "pmount" ); + if( !pmountBin.isEmpty() ) { + KProcess p; + p << pmountBin; + p << mntDev; + p.start( KProcess::Block ); + return !p.exitStatus(); + } + return false; +} + + +bool K3b::eject( K3bDevice::Device* dev ) +{ +#ifdef HAVE_HAL + if( !K3bDevice::HalConnection::instance()->eject( dev ) ) + return true; +#endif + + if( K3b::isMounted( dev ) ) + K3b::unmount( dev ); + + return dev->eject(); +} diff --git a/libk3b/core/k3bglobals.h b/libk3b/core/k3bglobals.h new file mode 100644 index 0000000..2795630 --- /dev/null +++ b/libk3b/core/k3bglobals.h @@ -0,0 +1,257 @@ +/* + * + * $Id: k3bglobals.h 630384 2007-02-05 09:33:17Z mlaurent $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BGLOBALS_H +#define K3BGLOBALS_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "k3b_export.h" + +class KConfig; +class K3bVersion; +class K3bExternalBin; + + +#include + + +#ifdef HAVE_STAT64 +#define k3b_struct_stat struct stat64 +#define k3b_stat ::stat64 +#define k3b_lstat ::lstat64 +#else +#define k3b_struct_stat struct stat +#define k3b_stat ::stat +#define k3b_lstat ::lstat +#endif + + +namespace K3bDevice { + class Device; +} + +namespace K3b +{ + enum WritingApp { + DEFAULT = 1, + CDRECORD = 2, + CDRDAO = 4, + DVDRECORD = 8, + GROWISOFS = 16, + DVD_RW_FORMAT = 32 + }; + + LIBK3B_EXPORT int writingAppFromString( const QString& ); + + /** + * DATA_MODE_AUTO - let K3b determine the best mode + * MODE1 - refers to the default Yellow book mode1 + * MODE2 - refers to CDROM XA mode2 form1 + */ + enum DataMode { + DATA_MODE_AUTO, + MODE1, + MODE2 + }; + + /** + * The sector size denotes the number of bytes K3b provides per sector. + * This is based on the sizes cdrecord's -data, -xa, and -xamix parameters + * demand. + */ + enum SectorSize { + SECTORSIZE_AUDIO = 2352, + SECTORSIZE_DATA_2048 = 2048, + SECTORSIZE_DATA_2048_SUBHEADER = 2056, + SECTORSIZE_DATA_2324 = 2324, + SECTORSIZE_DATA_2324_SUBHEADER = 2332, + SECTORSIZE_RAW = 2448 + }; + + /** + * AUTO - let K3b determine the best mode + * TAO - Track at once + * DAO - Disk at once (or session at once) + * RAW - Raw mode + * + * may be or'ed together (except for WRITING_MODE_AUTO of course) + */ + enum WritingMode { + WRITING_MODE_AUTO = 0, + TAO = K3bDevice::WRITINGMODE_TAO, + DAO = K3bDevice::WRITINGMODE_SAO, + RAW = K3bDevice::WRITINGMODE_RAW, + WRITING_MODE_INCR_SEQ = K3bDevice::WRITINGMODE_INCR_SEQ, // Incremental Sequential + WRITING_MODE_RES_OVWR = K3bDevice::WRITINGMODE_RES_OVWR // Restricted Overwrite + }; + + LIBK3B_EXPORT QString writingModeString( int ); + + LIBK3B_EXPORT QString framesToString( int h, bool showFrames = true ); + /*LIBK3B_EXPORT QString sizeToTime( long size );*/ + + LIBK3B_EXPORT Q_INT16 swapByteOrder( const Q_INT16& i ); + LIBK3B_EXPORT Q_INT32 swapByteOrder( const Q_INT32& i ); + LIBK3B_EXPORT Q_INT64 swapByteOrder( const Q_INT64& i ); + + int round( double ); + + /** + * This checks the free space on the filesystem path is in. + * We use this since we encountered problems with the KDE version. + * @returns true on success. + */ + LIBK3B_EXPORT bool kbFreeOnFs( const QString& path, unsigned long& size, unsigned long& avail ); + + /** + * Cut a filename preserving the extension + */ + LIBK3B_EXPORT QString cutFilename( const QString& name, unsigned int len ); + + LIBK3B_EXPORT QString removeFilenameExtension( const QString& name ); + + /** + * Append a number to a filename preserving the extension. + * The resulting name's length will not exceed @p maxlen + */ + LIBK3B_EXPORT QString appendNumberToFilename( const QString& name, int num, unsigned int maxlen ); + + LIBK3B_EXPORT QString findUniqueFilePrefix( const QString& _prefix = QString::null, const QString& path = QString::null ); + + /** + * Find a unique filename in directory d (if d is empty the method uses the defaultTempPath) + */ + LIBK3B_EXPORT QString findTempFile( const QString& ending = QString::null, const QString& d = QString::null ); + + /** + * Wrapper around KStandardDirs::findExe which searches the PATH and some additional + * directories to find system tools which are normally only in root's PATH. + */ + LIBK3B_EXPORT QString findExe( const QString& name ); + + /** + * get the default K3b temp path to store image files + */ + LIBK3B_EXPORT QString defaultTempPath(); + + /** + * makes sure a path ends with a "/" + */ + LIBK3B_EXPORT QString prepareDir( const QString& dir ); + + /** + * returns the parent dir of a path. + * CAUTION: this does only work well with absolut paths. + * + * Example: /usr/share/doc -> /usr/share/ + */ + QString parentDir( const QString& path ); + + /** + * For now this just replaces multiple occurrences of / with a single / + */ + LIBK3B_EXPORT QString fixupPath( const QString& ); + + /** + * resolves a symlinks completely. Meaning it also handles links to links to links... + */ + LIBK3B_EXPORT QString resolveLink( const QString& ); + + LIBK3B_EXPORT K3bVersion kernelVersion(); + + /** + * Kernel version stripped of all suffixes + */ + LIBK3B_EXPORT K3bVersion simpleKernelVersion(); + + QString systemName(); + + LIBK3B_EXPORT KIO::filesize_t filesize( const KURL& ); + + /** + * Calculate the total size of an image file. This also includes + * images splitted by a K3bFileSplitter. + * + * \returns the total size of the image file at url + */ + LIBK3B_EXPORT KIO::filesize_t imageFilesize( const KURL& url ); + + /** + * true if the kernel supports ATAPI devices without SCSI emulation. + * use in combination with the K3bExternalProgram feature "plain-atapi" + */ + LIBK3B_EXPORT bool plainAtapiSupport(); + + /** + * true if the kernel supports ATAPI devices without SCSI emulation + * via the ATAPI: pseudo stuff + * use in combination with the K3bExternalProgram feature "hacked-atapi" + */ + LIBK3B_EXPORT bool hackedAtapiSupport(); + + /** + * Used to create a parameter for cdrecord, cdrdao or readcd. + * Takes care of SCSI and ATAPI. + */ + QString externalBinDeviceParameter( K3bDevice::Device* dev, const K3bExternalBin* ); + + /** + * Convert an url pointing to a local device to a K3bDevice. + * Supports media:// and system::// urls. + */ + LIBK3B_EXPORT K3bDevice::Device* urlToDevice( const KURL& deviceUrl ); + + /** + * Tries to convert urls from local protocols != "file" to file (for now supports media:/) + */ + LIBK3B_EXPORT KURL convertToLocalUrl( const KURL& url ); + LIBK3B_EXPORT KURL::List convertToLocalUrls( const KURL::List& l ); + + LIBK3B_EXPORT Q_INT16 fromLe16( char* ); + LIBK3B_EXPORT Q_INT32 fromLe32( char* ); + LIBK3B_EXPORT Q_INT64 fromLe64( char* ); + + LIBK3B_EXPORT bool isMounted( K3bDevice::Device* ); + + /** + * Tries to unmount the device ignoring its actual mounting state. + * This method uses both KIO::unmount and pumount if available. + */ + LIBK3B_EXPORT bool unmount( K3bDevice::Device* ); + + /** + * Tries to mount the medium. Since K3b does not gather any information + * about mount points the only methods used are pmount and HAL::mount + */ + LIBK3B_EXPORT bool mount( K3bDevice::Device* ); + + /** + * Ejects the medium in the device or simply opens the tray. + * This method improves over K3bDevice::Device::eject in that it + * unmounts before ejecting and introduces HAL support. + */ + LIBK3B_EXPORT bool eject( K3bDevice::Device* ); +} + +#endif diff --git a/libk3b/core/k3bglobalsettings.cpp b/libk3b/core/k3bglobalsettings.cpp new file mode 100644 index 0000000..6f58592 --- /dev/null +++ b/libk3b/core/k3bglobalsettings.cpp @@ -0,0 +1,61 @@ +/* + * + * $Id: k3bglobalsettings.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bglobalsettings.h" + +#include + + +K3bGlobalSettings::K3bGlobalSettings() + : m_eject(true), + m_burnfree(true), + m_overburn(false), + m_useManualBufferSize(false), + m_bufferSize(4), + m_force(false) +{ +} + + +void K3bGlobalSettings::readSettings( KConfig* c ) +{ + QString lastG = c->group(); + c->setGroup( "General Options" ); + + m_eject = !c->readBoolEntry( "No cd eject", false ); + m_burnfree = c->readBoolEntry( "burnfree", true ); + m_overburn = c->readBoolEntry( "Allow overburning", false ); + m_useManualBufferSize = c->readBoolEntry( "Manual buffer size", false ); + m_bufferSize = c->readNumEntry( "Fifo buffer", 4 ); + m_force = c->readBoolEntry( "Force unsafe operations", false ); + + c->setGroup( lastG ); +} + + +void K3bGlobalSettings::saveSettings( KConfig* c ) +{ + QString lastG = c->group(); + c->setGroup( "General Options" ); + + c->writeEntry( "No cd eject", !m_eject ); + c->writeEntry( "burnfree", m_burnfree ); + c->writeEntry( "Allow overburning", m_overburn ); + c->writeEntry( "Manual buffer size", m_useManualBufferSize ); + c->writeEntry( "Fifo buffer", m_bufferSize ); + c->writeEntry( "Force unsafe operations", m_force ); + + c->setGroup( lastG ); +} diff --git a/libk3b/core/k3bglobalsettings.h b/libk3b/core/k3bglobalsettings.h new file mode 100644 index 0000000..1194789 --- /dev/null +++ b/libk3b/core/k3bglobalsettings.h @@ -0,0 +1,70 @@ +/* + * + * $Id: k3bglobalsettings.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_GLOBAL_SETTINGS_H_ +#define _K3B_GLOBAL_SETTINGS_H_ +#include "k3b_export.h" +class KConfig; + +/** + * Some global settings used throughout K3b. + */ +class LIBK3B_EXPORT K3bGlobalSettings +{ + public: + K3bGlobalSettings(); + + /** + * This method takes care of settings the config group + */ + void readSettings( KConfig* ); + + /** + * This method takes care of settings the config group + */ + void saveSettings( KConfig* ); + + bool ejectMedia() const { return m_eject; } + bool burnfree() const { return m_burnfree; } + bool overburn() const { return m_overburn; } + bool useManualBufferSize() const { return m_useManualBufferSize; } + int bufferSize() const { return m_bufferSize; } + + /** + * If force is set to true K3b will continue in certain "unsafe" situations. + * The most common being a medium not suitable for the writer in terms of + * writing speed. + * Compare cdrecord's parameter -force + */ + bool force() const { return m_force; } + + void setEjectMedia( bool b ) { m_eject = b; } + void setBurnfree( bool b ) { m_burnfree = b; } + void setOverburn( bool b ) { m_overburn = b; } + void setUseManualBufferSize( bool b ) { m_useManualBufferSize = b; } + void setBufferSize( int size ) { m_bufferSize = size; } + void setForce( bool b ) { m_force = b; } + + private: + bool m_eject; + bool m_burnfree; + bool m_overburn; + bool m_useManualBufferSize; + int m_bufferSize; + bool m_force; +}; + + +#endif diff --git a/libk3b/core/k3bjob.cpp b/libk3b/core/k3bjob.cpp new file mode 100644 index 0000000..b545107 --- /dev/null +++ b/libk3b/core/k3bjob.cpp @@ -0,0 +1,253 @@ +/* + * + * $Id: k3bjob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bjob.h" +#include +#include + +#include +#include + +#include +#include + + +class K3bJob::Private +{ +public: +}; + + +const char* K3bJob::DEFAULT_SIGNAL_CONNECTION = "K3bJobDefault"; + + +K3bJob::K3bJob( K3bJobHandler* handler, QObject* parent, const char* name ) + : QObject( parent, name ), + m_jobHandler( handler ), + m_canceled(false), + m_active(false) +{ + connect( this, SIGNAL(canceled()), + this, SLOT(slotCanceled()) ); +} + +K3bJob::~K3bJob() +{ + // + // Normally a job (or the user of a job should take care of this + // but we do this here for security reasons. + // + if( m_active ) + jobFinished( false ); +} + + +void K3bJob::setJobHandler( K3bJobHandler* jh ) +{ + m_jobHandler = jh; +} + + +void K3bJob::jobStarted() +{ + m_canceled = false; + m_active = true; + + if( jobHandler() && jobHandler()->isJob() ) + static_cast(jobHandler())->registerSubJob( this ); + else + k3bcore->registerJob( this ); + + emit started(); +} + + +void K3bJob::jobFinished( bool success ) +{ + m_active = false; + + if( jobHandler() && jobHandler()->isJob() ) + static_cast(jobHandler())->unregisterSubJob( this ); + else + k3bcore->unregisterJob( this ); + + emit finished( success ); +} + + +void K3bJob::slotCanceled() +{ + m_canceled = true; +} + + +int K3bJob::waitForMedia( K3bDevice::Device* device, + int mediaState, + int mediaType, + const QString& message ) +{ + // TODO: What about: emit newSubTask( i18n("Waiting for media") ); + return m_jobHandler->waitForMedia( device, mediaState, mediaType, message ); +} + + +bool K3bJob::questionYesNo( const QString& text, + const QString& caption, + const QString& yesText, + const QString& noText ) +{ + return m_jobHandler->questionYesNo( text, caption, yesText, noText ); +} + + +void K3bJob::blockingInformation( const QString& text, + const QString& caption ) +{ + return m_jobHandler->blockingInformation( text, caption ); +} + + +void K3bJob::connectSubJob( K3bJob* subJob, + const char* finishedSlot, + bool connectProgress, + const char* progressSlot, + const char* subProgressSlot, + const char* processedSizeSlot, + const char* processedSubSizeSlot ) +{ + connect( subJob, SIGNAL(newTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( subJob, SIGNAL(newSubTask(const QString&)), this, SLOT(slotNewSubTask(const QString&)) ); + connect( subJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + connect( subJob, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + connect( subJob, SIGNAL(finished(bool)), this, finishedSlot ); + + if( connectProgress ) { + connect( subJob, SIGNAL(percent(int)), + this, progressSlot != 0 ? progressSlot : SIGNAL(subPercent(int)) ); + if( subProgressSlot ) + connect( subJob, SIGNAL(subPercent(int)), this, subProgressSlot ); + connect( subJob, SIGNAL(processedSize(int, int)), + this, processedSizeSlot != 0 ? processedSizeSlot : SIGNAL(processedSubSize(int, int)) ); + if( processedSubSizeSlot ) + connect( subJob, SIGNAL(processedSubSize(int, int)), this, processedSubSizeSlot ); + } +} + + +void K3bJob::connectSubJob( K3bJob* subJob, + const char* finishedSlot, + const char* newTaskSlot, + const char* newSubTaskSlot, + const char* progressSlot, + const char* subProgressSlot, + const char* processedSizeSlot, + const char* processedSubSizeSlot ) +{ + // standard connections + connect( subJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + connect( subJob, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + + // task connections + if( newTaskSlot == DEFAULT_SIGNAL_CONNECTION ) + connect( subJob, SIGNAL(newTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + else if( newTaskSlot ) + connect( subJob, SIGNAL(newTask(const QString&)), this, newTaskSlot ); + + if( newSubTaskSlot == DEFAULT_SIGNAL_CONNECTION ) + connect( subJob, SIGNAL(newSubTask(const QString&)), this, SLOT(slotNewSubTask(const QString&)) ); + else if( newSubTaskSlot ) + connect( subJob, SIGNAL(newSubTask(const QString&)), this, newSubTaskSlot ); + + if( finishedSlot && finishedSlot != DEFAULT_SIGNAL_CONNECTION ) + connect( subJob, SIGNAL(finished(bool)), this, finishedSlot ); + + // progress + if( progressSlot == DEFAULT_SIGNAL_CONNECTION ) + connect( subJob, SIGNAL(percent(int)), this, SIGNAL(subPercent(int)) ); + else if( progressSlot ) + connect( subJob, SIGNAL(percent(int)), this, progressSlot ); + + if( subProgressSlot && subProgressSlot != DEFAULT_SIGNAL_CONNECTION ) + connect( subJob, SIGNAL(subPercent(int)), this, subProgressSlot ); + + // processed size + if( processedSizeSlot == DEFAULT_SIGNAL_CONNECTION ) + connect( subJob, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + else if( processedSizeSlot ) + connect( subJob, SIGNAL(processedSize(int, int)), this, processedSizeSlot ); + + if( processedSubSizeSlot && processedSubSizeSlot != DEFAULT_SIGNAL_CONNECTION ) + connect( subJob, SIGNAL(processedSubSize(int, int)), this, processedSubSizeSlot ); +} + + +unsigned int K3bJob::numRunningSubJobs() const +{ + return m_runningSubJobs.count(); +} + + +void K3bJob::slotNewSubTask( const QString& str ) +{ + emit infoMessage( str, INFO ); +} + + +void K3bJob::registerSubJob( K3bJob* job ) +{ + m_runningSubJobs.append( job ); +} + + +void K3bJob::unregisterSubJob( K3bJob* job ) +{ + m_runningSubJobs.removeRef( job ); +} + + + + +class K3bBurnJob::Private +{ +public: +}; + + + +K3bBurnJob::K3bBurnJob( K3bJobHandler* handler, QObject* parent, const char* name ) + : K3bJob( handler, parent, name ), + m_writeMethod( K3b::DEFAULT ) +{ + d = new Private; +} + + +K3bBurnJob::~K3bBurnJob() +{ + delete d; +} + + +int K3bBurnJob::supportedWritingApps() const +{ + return K3b::DEFAULT | K3b::CDRDAO | K3b::CDRECORD; +} + +#include "k3bjob.moc" diff --git a/libk3b/core/k3bjob.h b/libk3b/core/k3bjob.h new file mode 100644 index 0000000..59e1f9b --- /dev/null +++ b/libk3b/core/k3bjob.h @@ -0,0 +1,311 @@ +/* + * + * $Id: k3bjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BJOB_H +#define K3BJOB_H + +#include +#include +#include "k3bjobhandler.h" +#include "k3b_export.h" + +class K3bDoc; +namespace K3bDevice { + class Device; +} + + +/** + * This is the baseclass for all the jobs in K3b which actually do the work like burning a cd! + * The K3bJob object takes care of registering with the k3bcore or with a parent K3bJob. + * + * Every job has a jobhandler which can be another job (in which case the job is handled as + * a subjob) or an arbitrary class implementing the K3bJobHandler interface. + * + * A Job should never create any widgets. User interaction should be done through the methods + * questionYesNo, waitForMedia. + * + * @author Sebastian Trueg + */ +class LIBK3B_EXPORT K3bJob : public QObject, public K3bJobHandler +{ + Q_OBJECT + + public: + virtual ~K3bJob(); + + /** + * \reimplemented from K3bJobHandler + */ + bool isJob() const { return true; } + + K3bJobHandler* jobHandler() const { return m_jobHandler; } + + /** + * Is the job active? + * The default implementation is based on the jobStarted() and jobFinished() + * methods and there is normally no need to reimplement this. + */ + virtual bool active() const { return m_active; } + + /** + * The default implementation is based on the canceled() signal. + * + * This means that one cannot count on this value being valid + * in a slot connected to the canceled() signal. It is, however, save + * to call this method from a slot connected to the finished() signal + * in case the job makes proper usage of the jobStarted/jobFinished + * methods. + */ + virtual bool hasBeenCanceled() const { return m_canceled; } + + virtual QString jobDescription() const { return "K3bJob"; } + virtual QString jobDetails() const { return QString::null; } + + /** + * @returns the number of running subjobs. + * this is useful for proper cancellation of jobs. + */ + unsigned int numRunningSubJobs() const; + + const QPtrList& runningSubJobs() const { return m_runningSubJobs; } + + /** + * \deprecated + */ + virtual void connectSubJob( K3bJob* subJob, + const char* finishedSlot = 0, + bool progress = false, + const char* progressSlot = 0, + const char* subProgressSot = 0, + const char* processedSizeSlot = 0, + const char* processedSubSizeSlot = 0 ); + + static const char* DEFAULT_SIGNAL_CONNECTION; + + /** + * \param newTaskSlot If DEFAULT_SIGNAL_CONNECTION the newTask signal from the subjob will + * be connected to the newSubTask signal + * \param newSubTaskSlot If DEFAULT_SIGNAL_CONNECTION the newSubTask signal from the subjob + * will create an infoMessage signal + * \param progressSlot If DEFAULT_SIGNAL_CONNECTION the percent signal of the subjob will be + * connected to the subPercent signal. + * debuggingOutput and infoMessage will always be direcctly connected. + * + * If a parameter is set to 0 it will not be connected at all + */ + virtual void connectSubJob( K3bJob* subJob, + const char* finishedSlot = DEFAULT_SIGNAL_CONNECTION, + const char* newTaskSlot = DEFAULT_SIGNAL_CONNECTION, + const char* newSubTaskSlot = DEFAULT_SIGNAL_CONNECTION, + const char* progressSlot = DEFAULT_SIGNAL_CONNECTION, + const char* subProgressSlot = DEFAULT_SIGNAL_CONNECTION, + const char* processedSizeSlot = DEFAULT_SIGNAL_CONNECTION, + const char* processedSubSizeSlot = DEFAULT_SIGNAL_CONNECTION ); + + /** + * Message types to be used in combination with the infoMessage signal. + * + * \see infoMessage() + */ + enum MessageType { + INFO, /**< Informational message. For example a message that informs the user about what is + currently going on */ + WARNING, /**< A warning message. Something did not go perfectly but the job may continue. */ + ERROR, /**< An error. Only use this message type if the job will actually fail afterwards + with a call to jobFinished( false ) */ + SUCCESS /**< This message type may be used to inform the user that a sub job has + been successfully finished. */ + }; + + /** + * reimplemented from K3bJobHandler + */ + int waitForMedia( K3bDevice::Device*, + int mediaState = K3bDevice::STATE_EMPTY, + int mediaType = K3bDevice::MEDIA_WRITABLE_CD, + const QString& message = QString::null ); + + /** + * reimplemented from K3bJobHandler + */ + bool questionYesNo( const QString& text, + const QString& caption = QString::null, + const QString& yesText = QString::null, + const QString& noText = QString::null ); + + /** + * reimplemented from K3bJobHandler + */ + void blockingInformation( const QString& text, + const QString& caption = QString::null ); + + public slots: + /** + * This is the slot that starts the job. The first call should always + * be jobStarted(). + * + * Once the job has finished it has to call jobFinished() with the result as + * a parameter. + * + * \see jobStarted() + * \see jobFinished() + */ + virtual void start() = 0; + + /** + * This slot should cancel the job. The job has to emit the canceled() signal and make a call + * to jobFinished(). + * It is not important to do any of those two directly in this slot though. + */ + virtual void cancel() = 0; + + void setJobHandler( K3bJobHandler* ); + + signals: + void infoMessage( const QString& msg, int type ); + void percent( int p ); + void subPercent( int p ); + void processedSize( int processed, int size ); + void processedSubSize( int processed, int size ); + void newTask( const QString& job ); + void newSubTask( const QString& job ); + void debuggingOutput(const QString&, const QString&); + void data( const char* data, int len ); + void nextTrack( int track, int numTracks ); + + void canceled(); + + /** + * Emitted once the job has been started. Never emit this signal directly. + * Use jobStarted() instead, otherwise the job will not be properly registered + */ + void started(); + + /** + * Emitted once the job has been finshed. Never emit this signal directly. + * Use jobFinished() instead, otherwise the job will not be properly deregistered + */ + void finished( bool success ); + + protected: + /** + * \param hdl the handler of the job. This allows for some user interaction without + * specifying any details (like the GUI). + * The job handler can also be another job. In that case this job is a sub job + * and will be part of the parents running sub jobs. + * + * \see runningSubJobs() + * \see numRunningSubJobs() + */ + K3bJob( K3bJobHandler* hdl, QObject* parent = 0, const char* name = 0 ); + + /** + * Call this in start() to properly register the job and emit the started() signal. + * Do never emit the started() signal manually. + * + * Always call K3bJob::jobStarted in reimplementations. + */ + virtual void jobStarted(); + + /** + * Call this at the end of the job to properly deregister the job and emit the finished() signal. + * Do never emit the started() signal manually. + * + * Always call K3bJob::jobFinished in reimplementations. + */ + virtual void jobFinished( bool success ); + + private slots: + void slotCanceled(); + void slotNewSubTask( const QString& str ); + + private: + void registerSubJob( K3bJob* ); + void unregisterSubJob( K3bJob* ); + + K3bJobHandler* m_jobHandler; + QPtrList m_runningSubJobs; + + bool m_canceled; + bool m_active; + + class Private; + Private* d; +}; + + +/** + * Every job used to actually burn a medium is derived from K3bBurnJob. + * This class implements additional signals like buffer status or writing speed + * as well as a handling of the used writing application. + */ +class LIBK3B_EXPORT K3bBurnJob : public K3bJob +{ + Q_OBJECT + + public: + K3bBurnJob( K3bJobHandler* hdl, QObject* parent = 0, const char* name = 0 ); + virtual ~K3bBurnJob(); + + /** + * The writing device used by this job. + */ + virtual K3bDevice::Device* writer() const { return 0; } + + /** + * use K3b::WritingApp + */ + int writingApp() const { return m_writeMethod; } + + /** + * K3b::WritingApp "ored" together + */ + virtual int supportedWritingApps() const; + + public slots: + /** + * use K3b::WritingApp + */ + void setWritingApp( int w ) { m_writeMethod = w; } + + signals: + void bufferStatus( int ); + + void deviceBuffer( int ); + + /** + * @param speed current writing speed in Kb + * @param multiplicator use 150 for CDs and 1380 for DVDs + * FIXME: maybe one should be able to ask the burnjob if it burns a CD or a DVD and remove the + * multiplicator parameter) + */ + void writeSpeed( int speed, int multiplicator ); + + /** + * This signal may be used to inform when the burning starts or ends + * The BurningProgressDialog for example uses it to enable and disable + * the buffer and writing speed displays. + */ + void burning(bool); + + private: + int m_writeMethod; + + class Private; + Private* d; +}; +#endif diff --git a/libk3b/core/k3bjobhandler.h b/libk3b/core/k3bjobhandler.h new file mode 100644 index 0000000..1262e0e --- /dev/null +++ b/libk3b/core/k3bjobhandler.h @@ -0,0 +1,64 @@ +/* + * + * $Id: k3bjobhandler.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_JOB_HANDLER_H_ +#define _K3B_JOB_HANDLER_H_ + + +#include +#include + + +/** + * See @p K3bJobProgressDialog as an example for the usage of + * the K3bJobHandler interface. + */ +class K3bJobHandler +{ + public: + K3bJobHandler() {} + virtual ~K3bJobHandler() {} + + /** + * \return true if the handler itself is also a job + */ + virtual bool isJob() const { return false; } + + /** + * @return K3bDevice::MediaType on success, + * 0 if forced (no media info available), + * and -1 on error (canceled) + */ + virtual int waitForMedia( K3bDevice::Device*, + int mediaState = K3bDevice::STATE_EMPTY, + int mediaType = K3bDevice::MEDIA_WRITABLE_CD, + const QString& message = QString::null ) = 0; + + // FIXME: use KGuiItem + virtual bool questionYesNo( const QString& text, + const QString& caption = QString::null, + const QString& yesText = QString::null, + const QString& noText = QString::null ) = 0; + + /** + * Use this if you need the user to do something before the job is able to continue. + * In all other cases an infoMessage should be used. + */ + virtual void blockingInformation( const QString& text, + const QString& caption = QString::null ) = 0; + +}; + +#endif diff --git a/libk3b/core/k3bprocess.cpp b/libk3b/core/k3bprocess.cpp new file mode 100644 index 0000000..35ddff4 --- /dev/null +++ b/libk3b/core/k3bprocess.cpp @@ -0,0 +1,452 @@ +/* + * + * $Id: k3bprocess.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#include "k3bprocess.h" +#include "k3bexternalbinmanager.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + + +class K3bProcess::Data +{ +public: + QString unfinishedStdoutLine; + QString unfinishedStderrLine; + + int dupStdoutFd; + int dupStdinFd; + + bool rawStdin; + bool rawStdout; + + int in[2]; + int out[2]; + + bool suppressEmptyLines; +}; + + +K3bProcess::K3bProcess() + : KProcess(), + m_bSplitStdout(false) +{ + d = new Data(); + d->dupStdinFd = d->dupStdoutFd = -1; + d->rawStdout = d->rawStdin = false; + d->in[0] = d->in[1] = -1; + d->out[0] = d->out[1] = -1; + d->suppressEmptyLines = true; +} + +K3bProcess::~K3bProcess() +{ + delete d; +} + + +K3bProcess& K3bProcess::operator<<( const K3bExternalBin* bin ) +{ + return this->operator<<( bin->path ); +} + +K3bProcess& K3bProcess::operator<<( const QString& arg ) +{ + static_cast(this)->operator<<( arg ); + return *this; +} + +K3bProcess& K3bProcess::operator<<( const char* arg ) +{ + static_cast(this)->operator<<( arg ); + return *this; +} + +K3bProcess& K3bProcess::operator<<( const QCString& arg ) +{ + static_cast(this)->operator<<( arg ); + return *this; +} + +K3bProcess& K3bProcess::operator<<( const QStringList& args ) +{ + static_cast(this)->operator<<( args ); + return *this; +} + + +bool K3bProcess::start( RunMode run, Communication com ) +{ + if( com & Stderr ) { + connect( this, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotSplitStderr(KProcess*, char*, int)) ); + } + if( com & Stdout ) { + connect( this, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotSplitStdout(KProcess*, char*, int)) ); + } + + return KProcess::start( run, com ); +} + + +void K3bProcess::slotSplitStdout( KProcess*, char* data, int len ) +{ + if( m_bSplitStdout ) { + QStringList lines = splitOutput( data, len, d->unfinishedStdoutLine, d->suppressEmptyLines ); + + for( QStringList::iterator it = lines.begin(); it != lines.end(); ++it ) { + QString& str = *it; + + // just to be sure since something in splitOutput does not do this right + if( d->suppressEmptyLines && str.isEmpty() ) + continue; + + emit stdoutLine( str ); + } + } +} + + +void K3bProcess::slotSplitStderr( KProcess*, char* data, int len ) +{ + QStringList lines = splitOutput( data, len, d->unfinishedStderrLine, d->suppressEmptyLines ); + + for( QStringList::iterator it = lines.begin(); it != lines.end(); ++it ) { + QString& str = *it; + + // just to be sure since something in splitOutput does not do this right + if( d->suppressEmptyLines && str.isEmpty() ) + continue; + + emit stderrLine( str ); + } +} + + +QStringList K3bProcess::splitOutput( char* data, int len, + QString& unfinishedLine, bool suppressEmptyLines ) +{ + // + // The stderr splitting is mainly used for parsing of messages + // That's why we simplify the data before proceeding + // + + QString buffer; + for( int i = 0; i < len; i++ ) { + if( data[i] == '\b' ) { + while( data[i] == '\b' ) // we replace multiple backspaces with a single line feed + i++; + buffer += '\n'; + } + if( data[i] == '\r' ) + buffer += '\n'; + else if( data[i] == '\t' ) // replace tabs with a single space + buffer += " "; + else + buffer += data[i]; + } + + QStringList lines = QStringList::split( '\n', buffer, !suppressEmptyLines ); + + // in case we suppress empty lines we need to handle the following separately + // to make sure we join unfinished lines correctly + if( suppressEmptyLines && buffer[0] == '\n' ) + lines.prepend( QString::null ); + + if( !unfinishedLine.isEmpty() ) { + lines.first().prepend( unfinishedLine ); + unfinishedLine.truncate(0); + + kdDebug() << "(K3bProcess) joined line: '" << (lines.first()) << "'" << endl; + } + + QStringList::iterator it; + + // check if line ends with a newline + // if not save the last line because it is not finished + QChar c = buffer.right(1).at(0); + bool hasUnfinishedLine = ( c != '\n' && c != '\r' && c != QChar(46) ); // What is unicode 46?? It is printed as a point + if( hasUnfinishedLine ) { + kdDebug() << "(K3bProcess) found unfinished line: '" << lines.last() << "'" << endl; + kdDebug() << "(K3bProcess) last char: '" << buffer.right(1) << "'" << endl; + unfinishedLine = lines.last(); + it = lines.end(); + --it; + lines.remove(it); + } + + return lines; +} + + +int K3bProcess::setupCommunication( Communication comm ) +{ + if( KProcess::setupCommunication( comm ) ) { + + // + // Setup our own socketpair + // + + if( d->rawStdin ) { + if( socketpair(AF_UNIX, SOCK_STREAM, 0, d->in) == 0 ) { + fcntl(d->in[0], F_SETFD, FD_CLOEXEC); + fcntl(d->in[1], F_SETFD, FD_CLOEXEC); + } + else + return 0; + } + + if( d->rawStdout ) { + if( socketpair(AF_UNIX, SOCK_STREAM, 0, d->out) == 0 ) { + fcntl(d->out[0], F_SETFD, FD_CLOEXEC); + fcntl(d->out[1], F_SETFD, FD_CLOEXEC); + } + else { + if( d->rawStdin || d->dupStdinFd ) { + close(d->in[0]); + close(d->in[1]); + } + return 0; + } + } + + return 1; + } + else + return 0; +} + + +void K3bProcess::commClose() +{ + if( d->rawStdin ) { + close(d->in[1]); + d->in[1] = -1; + } + if( d->rawStdout ) { + close(d->out[0]); + d->out[0] = -1; + } + + KProcess::commClose(); +} + + +int K3bProcess::commSetupDoneP() +{ + int ok = KProcess::commSetupDoneP(); + + if( d->rawStdin ) + close(d->in[0]); + if( d->rawStdout ) + close(d->out[1]); + + d->in[0] = d->out[1] = -1; + + return ok; +} + + +int K3bProcess::commSetupDoneC() +{ + int ok = KProcess::commSetupDoneC(); + + if( d->dupStdoutFd != -1 ) { + // + // make STDOUT_FILENO a duplicate of d->dupStdoutFd such that writes to STDOUT_FILENO are "redirected" + // to d->dupStdoutFd + // + if( ::dup2( d->dupStdoutFd, STDOUT_FILENO ) < 0 ) { + kdDebug() << "(K3bProcess) Error while dup( " << d->dupStdoutFd << ", " << STDOUT_FILENO << endl; + ok = 0; + } + } + else if( d->rawStdout ) { + if( ::dup2( d->out[1], STDOUT_FILENO ) < 0 ) { + kdDebug() << "(K3bProcess) Error while dup( " << d->out[1] << ", " << STDOUT_FILENO << endl; + ok = 0; + } + } + + if( d->dupStdinFd != -1 ) { + if( ::dup2( d->dupStdinFd, STDIN_FILENO ) < 0 ) { + kdDebug() << "(K3bProcess) Error while dup( " << d->dupStdinFd << ", " << STDIN_FILENO << endl; + ok = 0; + } + } + else if( d->rawStdin ) { + if( ::dup2( d->in[0], STDIN_FILENO ) < 0 ) { + kdDebug() << "(K3bProcess) Error while dup( " << d->in[0] << ", " << STDIN_FILENO << endl; + ok = 0; + } + } + + return ok; +} + + + +int K3bProcess::stdinFd() const +{ + if( d->rawStdin ) + return d->in[1]; + else if( d->dupStdinFd != -1 ) + return d->dupStdinFd; + else + return -1; +} + +int K3bProcess::stdoutFd() const +{ + if( d->rawStdout ) + return d->out[0]; + else if( d->dupStdoutFd != -1 ) + return d->dupStdoutFd; + else + return -1; +} + + +void K3bProcess::dupStdout( int fd ) +{ + writeToFd( fd ); +} + +void K3bProcess::dupStdin( int fd ) +{ + readFromFd( fd ); +} + + +void K3bProcess::writeToFd( int fd ) +{ + d->dupStdoutFd = fd; + if( fd != -1 ) + d->rawStdout = false; +} + +void K3bProcess::readFromFd( int fd ) +{ + d->dupStdinFd = fd; + if( fd != -1 ) + d->rawStdin = false; +} + + +void K3bProcess::setRawStdin(bool b) +{ + if( b ) { + d->rawStdin = true; + d->dupStdinFd = -1; + } + else + d->rawStdin = false; +} + + +void K3bProcess::setRawStdout(bool b) +{ + if( b ) { + d->rawStdout = true; + d->dupStdoutFd = -1; + } + else + d->rawStdout = false; +} + + +void K3bProcess::setSuppressEmptyLines( bool b ) +{ + d->suppressEmptyLines = b; +} + + +bool K3bProcess::closeStdin() +{ + if( d->rawStdin ) { + close(d->in[1]); + d->in[1] = -1; + return true; + } + else + return KProcess::closeStdin(); +} + + +bool K3bProcess::closeStdout() +{ + if( d->rawStdout ) { + close(d->out[0]); + d->out[0] = -1; + return true; + } + else + return KProcess::closeStdout(); +} + + +K3bProcessOutputCollector::K3bProcessOutputCollector( KProcess* p ) + : m_process(0) +{ + setProcess( p ); +} + +void K3bProcessOutputCollector::setProcess( KProcess* p ) +{ + if( m_process ) + m_process->disconnect( this ); + + m_process = p; + if( p ) { + connect( p, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotGatherStdout(KProcess*, char*, int)) ); + connect( p, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotGatherStderr(KProcess*, char*, int)) ); + } + + m_gatheredOutput.truncate( 0 ); + m_stderrOutput.truncate( 0 ); + m_stdoutOutput.truncate( 0 ); +} + +void K3bProcessOutputCollector::slotGatherStderr( KProcess*, char* data, int len ) +{ + m_gatheredOutput.append( QString::fromLocal8Bit( data, len ) ); + m_stderrOutput.append( QString::fromLocal8Bit( data, len ) ); +} + +void K3bProcessOutputCollector::slotGatherStdout( KProcess*, char* data, int len ) +{ + m_gatheredOutput.append( QString::fromLocal8Bit( data, len ) ); + m_stdoutOutput.append( QString::fromLocal8Bit( data, len ) ); +} + + +#include "k3bprocess.moc" diff --git a/libk3b/core/k3bprocess.h b/libk3b/core/k3bprocess.h new file mode 100644 index 0000000..959bda1 --- /dev/null +++ b/libk3b/core/k3bprocess.h @@ -0,0 +1,204 @@ +/* + * + * $Id: k3bprocess.h 621644 2007-01-09 12:53:09Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3B_PROCESS_H +#define K3B_PROCESS_H + + +#include +#include +#include "k3b_export.h" + +class K3bExternalBin; + + +/** + * This is an enhanced KProcess. + * It splits the stderr output to lines making sure the client gets every line as it + * was written by the process. + * Aditionally one may set raw stdout and stdin handling using the stdin() and stdout() methods + * to get the process' file descriptors. + * Last but not least K3bProcess is able to duplicate stdout making it possible to connect two + * K3bProcesses like used in K3bDataJob to duplicate mkisofs' stdout to the stdin of the writer + * (cdrecord or cdrdao) + */ +class LIBK3B_EXPORT K3bProcess : public KProcess +{ + Q_OBJECT + + public: + class OutputCollector; + + public: + K3bProcess(); + ~K3bProcess(); + + /** + * In the future this might also set the nice value + */ + K3bProcess& operator<<( const K3bExternalBin* ); + + K3bProcess& operator<<( const QString& arg ); + K3bProcess& operator<<( const char* arg ); + K3bProcess& operator<<( const QCString& arg ); + K3bProcess& operator<<( const QStringList& args ); + + bool start( RunMode run = NotifyOnExit, Communication com = NoCommunication ); + + /** + * get stdin file descriptor + * Only makes sense while process is running. + * + * Only use with setRawStdin + */ + int stdinFd() const; + + /** + * get stdout file descriptor + * Only makes sense while process is running. + * + * Only use with setRawStdout + */ + int stdoutFd() const; + + /** + * @deprecated use writeToFd + */ + void dupStdout( int fd ); + + /** + * @deprecated use readFromFd + */ + void dupStdin( int fd ); + + /** + * Make the process write to @fd instead of Stdout. + * This means you won't get any stdoutReady() or receivedStdout() + * signals anymore. + * + * Only use this before starting the process. + */ + void writeToFd( int fd ); + + /** + * Make the process read from @fd instead of Stdin. + * This means you won't get any wroteStdin() + * signals anymore. + * + * Only use this before starting the process. + */ + void readFromFd( int fd ); + + /** + * If set true the process' stdin fd will be available + * through @stdinFd. + * Be aware that you will not get any wroteStdin signals + * anymore. + * + * Only use this before starting the process. + */ + void setRawStdin(bool b); + + /** + * If set true the process' stdout fd will be available + * through @stdoutFd. + * Be aware that you will not get any stdoutReady or receivedStdout + * signals anymore. + * + * Only use this before starting the process. + */ + void setRawStdout(bool b); + + public slots: + void setSplitStdout( bool b ) { m_bSplitStdout = b; } + + /** + * default is true + */ + void setSuppressEmptyLines( bool b ); + + bool closeStdin(); + bool closeStdout(); + + private slots: + void slotSplitStderr( KProcess*, char*, int ); + void slotSplitStdout( KProcess*, char*, int ); + + signals: + void stderrLine( const QString& line ); + void stdoutLine( const QString& line ); + + /** + * Gets emitted if raw stdout mode has been requested + * The data has to be read from @p fd. + */ + void stdoutReady( int fd ); + + protected: + /** + * reimplemeted from KProcess + */ + int commSetupDoneP(); + + /** + * reimplemeted from KProcess + */ + int commSetupDoneC(); + + /** + * reimplemeted from KProcess + */ + int setupCommunication( Communication comm ); + + /** + * reimplemeted from KProcess + */ + void commClose(); + + private: + static QStringList splitOutput( char*, int, QString&, bool ); + + class Data; + Data* d; + + bool m_bSplitStdout; +}; + +class LIBK3B_EXPORT K3bProcessOutputCollector: public QObject +{ + Q_OBJECT + + public: + K3bProcessOutputCollector( KProcess* ); + void setProcess( KProcess* ); + + const QString& output() const { return m_gatheredOutput; } + const QString& stderrOutput() const { return m_stderrOutput; } + const QString& stdoutOutput() const { return m_stdoutOutput; } + + private slots: + void slotGatherStderr( KProcess*, char*, int ); + void slotGatherStdout( KProcess*, char*, int ); + + private: + QString m_gatheredOutput; + QString m_stderrOutput; + QString m_stdoutOutput; + KProcess* m_process; +}; + + +#endif diff --git a/libk3b/core/k3bprogressinfoevent.h b/libk3b/core/k3bprogressinfoevent.h new file mode 100644 index 0000000..0e77718 --- /dev/null +++ b/libk3b/core/k3bprogressinfoevent.h @@ -0,0 +1,85 @@ +/* + * + * $Id: k3bprogressinfoevent.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_PROGRESS_INFO_EVENT_H +#define K3B_PROGRESS_INFO_EVENT_H + +#include +#include + + +/** + * Custom event class for posting events corresponding to the + * K3bJob signals. This is useful for a threaded job since + * in that case it's not possible to emit signals that directly + * change the GUI (see QThread docu). + */ +class K3bProgressInfoEvent : public QCustomEvent +{ + public: + K3bProgressInfoEvent( int type ) + : QCustomEvent( type ), + m_type(type) + {} + + K3bProgressInfoEvent( int type, const QString& v1, const QString& v2 = QString::null, + int value1 = 0, int value2 = 0 ) + : QCustomEvent( type ), + m_type( type), + m_firstValue(value1), + m_secondValue(value2), + m_firstString(v1), + m_secondString(v2) + {} + + K3bProgressInfoEvent( int type, int value1, int value2 = 0 ) + : QCustomEvent( type ), + m_type( type), + m_firstValue(value1), + m_secondValue(value2) + {} + + int type() const { return m_type; } + const QString& firstString() const { return m_firstString; } + const QString& secondString() const { return m_secondString; } + int firstValue() const { return m_firstValue; } + int secondValue() const { return m_secondValue; } + + enum K3bProgressInfoEventType { + Progress = QEvent::User + 1, + SubProgress, + ProcessedSize, + ProcessedSubSize, + InfoMessage, + Started, + Canceled, + Finished, + NewTask, + NewSubTask, + DebuggingOutput, + BufferStatus, + WriteSpeed, + NextTrack + }; + + private: + int m_type; + int m_firstValue; + int m_secondValue; + QString m_firstString; + QString m_secondString; +}; + +#endif diff --git a/libk3b/core/k3bsimplejobhandler.cpp b/libk3b/core/k3bsimplejobhandler.cpp new file mode 100644 index 0000000..eaf7cd6 --- /dev/null +++ b/libk3b/core/k3bsimplejobhandler.cpp @@ -0,0 +1,62 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bsimplejobhandler.h" + + +K3bSimpleJobHandler::K3bSimpleJobHandler( QObject* parent ) + : QObject( parent ), + K3bJobHandler() +{ +} + +K3bSimpleJobHandler::~K3bSimpleJobHandler() +{ +} + +int K3bSimpleJobHandler::waitForMedia( K3bDevice::Device* dev, + int mediaState, + int mediaType, + const QString& message ) +{ + Q_UNUSED( dev ); + Q_UNUSED( mediaState ); + Q_UNUSED( mediaType ); + Q_UNUSED( message ); + + return 0; +} + +bool K3bSimpleJobHandler::questionYesNo( const QString& text, + const QString& caption, + const QString& yesText, + const QString& noText ) +{ + Q_UNUSED( text ); + Q_UNUSED( caption ); + Q_UNUSED( yesText ); + Q_UNUSED( noText ); + + return true; +} + +void K3bSimpleJobHandler::blockingInformation( const QString& text, + const QString& caption ) +{ + Q_UNUSED( text ); + Q_UNUSED( caption ); +} + +#include "k3bsimplejobhandler.moc" diff --git a/libk3b/core/k3bsimplejobhandler.h b/libk3b/core/k3bsimplejobhandler.h new file mode 100644 index 0000000..f84064e --- /dev/null +++ b/libk3b/core/k3bsimplejobhandler.h @@ -0,0 +1,61 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_SIMPLE_JOB_HANDLER_H_ +#define _K3B_SIMPLE_JOB_HANDLER_H_ + +#include + +#include +#include + + +/** + * This is a simplified job handler which just consumes the + * job handler calls without doing anything. + * Use it for very simple jobs that don't need the job handler + * methods. + */ +class LIBK3B_EXPORT K3bSimpleJobHandler : public QObject, public K3bJobHandler +{ + Q_OBJECT + + public: + K3bSimpleJobHandler( QObject* parent = 0 ); + ~K3bSimpleJobHandler(); + + /* + * \return 0 + */ + int waitForMedia( K3bDevice::Device*, + int mediaState = K3bDevice::STATE_EMPTY, + int mediaType = K3bDevice::MEDIA_WRITABLE_CD, + const QString& message = QString::null ); + /** + * \return true + */ + bool questionYesNo( const QString& text, + const QString& caption = QString::null, + const QString& yesText = QString::null, + const QString& noText = QString::null ); + + /** + * Does nothing + */ + void blockingInformation( const QString& text, + const QString& caption = QString::null ); +}; + +#endif diff --git a/libk3b/core/k3bthread.cpp b/libk3b/core/k3bthread.cpp new file mode 100644 index 0000000..07414ad --- /dev/null +++ b/libk3b/core/k3bthread.cpp @@ -0,0 +1,221 @@ +/* + * + * $Id: k3bthread.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bthread.h" +#include "k3bprogressinfoevent.h" +#include "k3bdataevent.h" + +#include + +#include + + +static QPtrList s_threads; + + +void K3bThread::waitUntilFinished() +{ + QPtrListIterator it( s_threads ); + while( it.current() ) { + kdDebug() << "Waiting for thread " << it.current() << endl; + it.current()->wait(); + ++it; + } + + kdDebug() << "Thread waiting done." << endl; +} + + +class K3bThread::Private +{ +public: + Private() + : eventHandler( 0 ) { + } + + QObject* eventHandler; +}; + + +K3bThread::K3bThread( QObject* eventHandler ) + : QThread() +{ + d = new Private; + d->eventHandler = eventHandler; + + s_threads.append(this); +} + + +K3bThread::K3bThread( unsigned int stackSize, QObject* eventHandler ) + : QThread( stackSize ) +{ + d = new Private; + d->eventHandler = eventHandler; + + s_threads.append(this); +} + + +K3bThread::~K3bThread() +{ + s_threads.removeRef(this); + delete d; +} + + +void K3bThread::setProgressInfoEventHandler( QObject* eventHandler ) +{ + d->eventHandler = eventHandler; +} + +QString K3bThread::jobDescription() const +{ + return QString::null; +} + + +QString K3bThread::jobDetails() const +{ + return QString::null; +} + + +void K3bThread::init() +{ + // do nothing... +} + + +void K3bThread::cancel() +{ + if( running() ) { + terminate(); + if( d->eventHandler ) { + emitCanceled(); + emitFinished(false); + } + } +} + + +void K3bThread::emitInfoMessage( const QString& msg, int type ) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, + new K3bProgressInfoEvent( K3bProgressInfoEvent::InfoMessage, msg, QString::null, type ) ); + else + kdWarning() << "(K3bThread) call to emitInfoMessage() without eventHandler." << endl; +} + +void K3bThread::emitPercent( int p ) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, + new K3bProgressInfoEvent( K3bProgressInfoEvent::Progress, p ) ); + else + kdWarning() << "(K3bThread) call to emitPercent() without eventHandler." << endl; +} + +void K3bThread::emitSubPercent( int p ) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, + new K3bProgressInfoEvent( K3bProgressInfoEvent::SubProgress, p ) ); + else + kdWarning() << "(K3bThread) call to emitSubPercent() without eventHandler." << endl; +} + +void K3bThread::emitStarted() +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, new K3bProgressInfoEvent( K3bProgressInfoEvent::Started ) ); + else + kdWarning() << "(K3bThread) call to emitStarted() without eventHandler." << endl; +} + +void K3bThread::emitCanceled() +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, new K3bProgressInfoEvent( K3bProgressInfoEvent::Canceled ) ); + else + kdWarning() << "(K3bThread) call to emitCanceled() without eventHandler." << endl; +} + +void K3bThread::emitFinished( bool success ) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, new K3bProgressInfoEvent( K3bProgressInfoEvent::Finished, success ) ); + else + kdWarning() << "(K3bThread) call to emitFinished() without eventHandler." << endl; +} + +void K3bThread::emitProcessedSize( int p, int size ) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, new K3bProgressInfoEvent( K3bProgressInfoEvent::ProcessedSize, p, size ) ); + else + kdWarning() << "(K3bThread) call to emitProcessedSize() without eventHandler." << endl; +} + +void K3bThread::emitProcessedSubSize( int p, int size ) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, new K3bProgressInfoEvent( K3bProgressInfoEvent::ProcessedSubSize, p, size ) ); + else + kdWarning() << "(K3bThread) call to emitProcessedSubSize() without eventHandler." << endl; +} + +void K3bThread::emitNewTask( const QString& job ) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, new K3bProgressInfoEvent( K3bProgressInfoEvent::NewTask, job ) ); + else + kdWarning() << "(K3bThread) call to emitNewTask() without eventHandler." << endl; +} + +void K3bThread::emitNewSubTask( const QString& job ) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, new K3bProgressInfoEvent( K3bProgressInfoEvent::NewSubTask, job ) ); + else + kdWarning() << "(K3bThread) call to emitNewSubTask() without eventHandler." << endl; +} + +void K3bThread::emitDebuggingOutput(const QString& group, const QString& text) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, new K3bProgressInfoEvent( K3bProgressInfoEvent::DebuggingOutput, group, text ) ); + else + kdWarning() << "(K3bThread) call to emitDebuggingOutput() without eventHandler." << endl; +} + +void K3bThread::emitData( const char* data, int len ) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, new K3bDataEvent( data, len ) ); + else + kdWarning() << "(K3bThread) call to emitData() without eventHandler." << endl; +} + +void K3bThread::emitNextTrack( int t, int n ) +{ + if( d->eventHandler ) + QApplication::postEvent( d->eventHandler, new K3bProgressInfoEvent( K3bProgressInfoEvent::NextTrack, t, n ) ); + else + kdWarning() << "(K3bThread) call to emitNextTrack() without eventHandler." << endl; +} + diff --git a/libk3b/core/k3bthread.h b/libk3b/core/k3bthread.h new file mode 100644 index 0000000..f7e68fc --- /dev/null +++ b/libk3b/core/k3bthread.h @@ -0,0 +1,95 @@ +/* + * + * $Id: k3bthread.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_THREAD_H_ +#define _K3B_THREAD_H_ + +#include +#include "k3b_export.h" + +class QObject; + +/** + * The threaded couterpart to K3bJob + * instead of emitting the information signals + * one has to use the emitXXX methods which will post + * K3bProgressInfoEvents to the eventhandler. + * + * K3bThreadJob can be used to automatically wrap the thread in a K3bJob. + * + * As in K3bJob it is important to call emitStarted and emitFinished. + * + * See K3bThreadJob for more information. + */ +class LIBK3B_EXPORT K3bThread : public QThread +{ + public: + K3bThread( QObject* eventHandler = 0 ); + K3bThread( unsigned int stackSize, QObject* eventHandler = 0 ); + virtual ~K3bThread(); + + void setProgressInfoEventHandler( QObject* eventHandler ); + + /** + * Initialize the thread before starting it in the GUi thread. + * K3bThreadJob automatically calls this. + * + * The default implementation does nothing. + */ + virtual void init(); + + /** + * to provide the same api like K3bJob + * the default implementation calls terminate and + * emitCancled() and emitFinished(false) + */ + virtual void cancel(); + + virtual QString jobDescription() const; + virtual QString jobDetails() const; + + /** + * waits until all running K3bThread have finished. + * This is used by K3bApplication. + */ + static void waitUntilFinished(); + + protected: + virtual void run() = 0; + + /** + * uses the K3bJob::MessageType enum + */ + void emitInfoMessage( const QString& msg, int type ); + void emitPercent( int p ); + void emitSubPercent( int p ); + void emitStarted(); + void emitCanceled(); + void emitFinished( bool success ); + void emitProcessedSize( int processed, int size ); + void emitProcessedSubSize( int processed, int size ); + void emitNewTask( const QString& job ); + void emitNewSubTask( const QString& job ); + void emitDebuggingOutput(const QString&, const QString&); + void emitData( const char* data, int len ); + void emitNextTrack( int track, int trackNum ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/core/k3bthreadjob.cpp b/libk3b/core/k3bthreadjob.cpp new file mode 100644 index 0000000..a13f10a --- /dev/null +++ b/libk3b/core/k3bthreadjob.cpp @@ -0,0 +1,161 @@ +/* + * + * $Id: k3bthreadjob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bthreadjob.h" +#include "k3bthread.h" +#include "k3bprogressinfoevent.h" +#include "k3bdataevent.h" + +#include +#include + + + +K3bThreadJob::K3bThreadJob( K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bJob( jh, parent, name ), + m_running(false) +{ +} + + +K3bThreadJob::K3bThreadJob( K3bThread* thread, K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bJob( jh, parent, name ), + m_running(false) +{ + setThread(thread); +} + + +K3bThreadJob::~K3bThreadJob() +{ +} + + +QString K3bThreadJob::jobDescription() const +{ + if( m_thread ) + return m_thread->jobDescription(); + else + return QString::null; +} + + +QString K3bThreadJob::jobDetails() const +{ + if( m_thread ) + return m_thread->jobDetails(); + else + return QString::null; +} + + +void K3bThreadJob::setThread( K3bThread* t ) +{ + m_thread = t; + m_thread->setProgressInfoEventHandler(this); +} + + +void K3bThreadJob::start() +{ + if( m_thread ) { + if( !m_running ) { + m_thread->setProgressInfoEventHandler(this); + m_running = true; + m_thread->init(); + m_thread->start(); + } + else + kdDebug() << "(K3bThreadJob) thread not finished yet." << endl; + } + else { + kdError() << "(K3bThreadJob) no job set." << endl; + jobFinished(false); + } +} + + +void K3bThreadJob::cancel() +{ + m_thread->cancel(); + // wait for the thread to finish + // m_thread->wait(); +} + + +void K3bThreadJob::cleanupJob( bool success ) +{ + Q_UNUSED( success ); +} + + +void K3bThreadJob::customEvent( QCustomEvent* e ) +{ + if( K3bDataEvent* de = dynamic_cast(e) ) { + emit data( de->data(), de->length() ); + } + else { + K3bProgressInfoEvent* be = static_cast(e); + switch( be->type() ) { + case K3bProgressInfoEvent::Progress: + emit percent( be->firstValue() ); + break; + case K3bProgressInfoEvent::SubProgress: + emit subPercent( be->firstValue() ); + break; + case K3bProgressInfoEvent::ProcessedSize: + emit processedSize( be->firstValue(), be->secondValue() ); + break; + case K3bProgressInfoEvent::ProcessedSubSize: + emit processedSubSize( be->firstValue(), be->secondValue() ); + break; + case K3bProgressInfoEvent::InfoMessage: + emit infoMessage( be->firstString(), be->firstValue() ); + break; + case K3bProgressInfoEvent::Started: + jobStarted(); + break; + case K3bProgressInfoEvent::Canceled: + emit canceled(); + break; + case K3bProgressInfoEvent::Finished: + // we wait until the thred really finished + // although this may be dangerous if some thread + // emits the finished signal although it has not finished yet + // but makes a lot stuff easier. + kdDebug() << "(K3bThreadJob) waiting for the thread to finish." << endl; + m_thread->wait(); + kdDebug() << "(K3bThreadJob) thread finished." << endl; + cleanupJob( be->firstValue() ); + m_running = false; + jobFinished( be->firstValue() ); + break; + case K3bProgressInfoEvent::NewTask: + emit newTask( be->firstString() ); + break; + case K3bProgressInfoEvent::NewSubTask: + emit newSubTask( be->firstString() ); + break; + case K3bProgressInfoEvent::DebuggingOutput: + emit debuggingOutput( be->firstString(), be->secondString() ); + break; + case K3bProgressInfoEvent::NextTrack: + emit nextTrack( be->firstValue(), be->secondValue() ); + break; + } + } +} + +#include "k3bthreadjob.moc" diff --git a/libk3b/core/k3bthreadjob.h b/libk3b/core/k3bthreadjob.h new file mode 100644 index 0000000..25919f1 --- /dev/null +++ b/libk3b/core/k3bthreadjob.h @@ -0,0 +1,89 @@ +/* + * + * $Id: k3bthreadjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_THREAD_JOB_H_ +#define _K3B_THREAD_JOB_H_ + +#include "k3bjob.h" +#include "k3b_export.h" +class QCustomEvent; +class K3bThread; + + +/** + * A Wrapper to use a K3bThread just like a K3bJob. + * Usage: + *
+ *   K3bThread* thread = new MySuperThread(...);
+ *   K3bThreadJob* job = new K3bThreadJob( thread, ... );
+ *   K3bBurnProgressDialog d;
+ *   d.setJob(job);
+ *   job->start();
+ *   d.exec();
+ *   delete job;
+ * 
+ * Be aware that K3bThreadJob'd destructor does NOT delete the thread. + */ +class LIBK3B_EXPORT K3bThreadJob : public K3bJob +{ + Q_OBJECT + + public: + K3bThreadJob( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + K3bThreadJob( K3bThread*, K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + virtual ~K3bThreadJob(); + + void setThread( K3bThread* t ); + K3bThread* thread() const { return m_thread; } + + /** + * \reimplemented from K3bJob + * + * \return true if the job has been started and has not yet + * emitted the finished signal + */ + virtual bool active() const { return m_running; } + + virtual QString jobDescription() const; + virtual QString jobDetails() const; + + public slots: + virtual void start(); + virtual void cancel(); + + protected: + /** + * converts K3bThread events to K3bJob signals + */ + virtual void customEvent( QCustomEvent* ); + + /** + * Reimplement this method to do some housekeeping once + * the thread has finished. + * + * The default implementation does nothing. + * + * \param success True if the thread finished successfully + */ + virtual void cleanupJob( bool success ); + + private: + K3bThread* m_thread; + bool m_running; +}; + +#endif + diff --git a/libk3b/core/k3bversion.cpp b/libk3b/core/k3bversion.cpp new file mode 100644 index 0000000..f7af248 --- /dev/null +++ b/libk3b/core/k3bversion.cpp @@ -0,0 +1,318 @@ +/* + * + * $Id: k3bversion.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bversion.h" + +#include +#include + + +K3bVersion::K3bVersion() + : m_majorVersion( -1 ), + m_minorVersion( -1 ), + m_patchLevel( -1 ) +{ +} + +K3bVersion::K3bVersion( const K3bVersion& v ) + : m_versionString( v.versionString() ), + m_majorVersion( v.majorVersion() ), + m_minorVersion( v.minorVersion() ), + m_patchLevel( v.patchLevel() ), + m_suffix( v.suffix() ) +{ +} + +K3bVersion::K3bVersion( const QString& version ) +{ + setVersion( version ); +} + +K3bVersion::K3bVersion( int majorVersion, + int minorVersion, + int patchlevel, + const QString& suffix ) +{ + setVersion( majorVersion, minorVersion, patchlevel, suffix ); +} + +void K3bVersion::setVersion( const QString& v ) +{ + QString suffix; + splitVersionString( v.stripWhiteSpace(), m_majorVersion, suffix ); + if( m_majorVersion >= 0 ) { + if( suffix.startsWith(".") ) { + suffix = suffix.mid( 1 ); + splitVersionString( suffix, m_minorVersion, suffix ); + if( m_minorVersion < 0 ) { + kdDebug() << "(K3bVersion) suffix must not start with a dot!" << endl; + m_majorVersion = -1; + m_minorVersion = -1; + m_patchLevel = -1; + m_suffix = ""; + } + else { + if( suffix.startsWith(".") ) { + suffix = suffix.mid( 1 ); + splitVersionString( suffix, m_patchLevel, suffix ); + if( m_patchLevel < 0 ) { + kdDebug() << "(K3bVersion) suffix must not start with a dot!" << endl; + m_majorVersion = -1; + m_minorVersion = -1; + m_patchLevel = -1; + m_suffix = ""; + } + else { + m_suffix = suffix; + } + } + else { + m_patchLevel = -1; + m_suffix = suffix; + } + } + } + else { + m_minorVersion = -1; + m_patchLevel = -1; + m_suffix = suffix; + } + } + + m_versionString = createVersionString( m_majorVersion, m_minorVersion, m_patchLevel, m_suffix ); +} + + +// splits the leading number from s and puts it in num +// the dot is removed and the rest put in suffix +// if s does not start with a digit or the first non-digit char is not a dot +// suffix = s and num = -1 is returned +void K3bVersion::splitVersionString( const QString& s, int& num, QString& suffix ) +{ + int pos = s.find( QRegExp("\\D") ); + if( pos < 0 ) { + num = s.toInt(); + suffix = ""; + } + else if( pos == 0 ) { + num = -1; + suffix = s; + } + else { + num = s.left( pos ).toInt(); + suffix = s.mid( pos ); + } +} + + +bool K3bVersion::isValid() const +{ + return (m_majorVersion >= 0); +} + + +void K3bVersion::setVersion( int majorVersion, + int minorVersion, + int patchlevel, + const QString& suffix ) +{ + m_majorVersion = majorVersion; + m_minorVersion = minorVersion; + m_patchLevel = patchlevel; + m_suffix = suffix; + m_versionString = createVersionString( majorVersion, minorVersion, patchlevel, suffix ); +} + +K3bVersion& K3bVersion::operator=( const QString& v ) +{ + setVersion( v ); + return *this; +} + +K3bVersion K3bVersion::simplify() const +{ + K3bVersion v( *this ); + v.m_suffix.truncate(0); + return v; +} + +QString K3bVersion::createVersionString( int majorVersion, + int minorVersion, + int patchlevel, + const QString& suffix ) +{ + if( majorVersion >= 0 ) { + QString s = QString::number(majorVersion); + + if( minorVersion > -1 ) { + s.append( QString(".%1").arg(minorVersion) ); + if( patchlevel > -1 ) + s.append( QString(".%1").arg(patchlevel) ); + } + + if( !suffix.isNull() ) + s.append( suffix ); + + return s; + } + else + return ""; +} + + +int K3bVersion::compareSuffix( const QString& suffix1, const QString& suffix2 ) +{ + static QRegExp rcRx( "rc(\\d+)" ); + static QRegExp preRx( "pre(\\d+)" ); + static QRegExp betaRx( "beta(\\d+)" ); + static QRegExp alphaRx( "a(?:lpha)?(\\d+)" ); + + // first we check if one of the suffixes (or both are empty) becasue that case if simple + if( suffix1.isEmpty() ) { + if( suffix2.isEmpty() ) + return 0; + else + return 1; // empty greater than the non-empty (should we treat something like 1.0a as greater than 1.0?) + } + else if( suffix2.isEmpty() ) + return -1; + + // now search for our special suffixes + if( rcRx.exactMatch( suffix1 ) ) { + int v1 = rcRx.cap(1).toInt(); + + if( rcRx.exactMatch( suffix2 ) ) { + int v2 = rcRx.cap(1).toInt(); + return ( v1 == v2 ? 0 : ( v1 < v2 ? -1 : 1 ) ); + } + else if( preRx.exactMatch( suffix2 ) || + betaRx.exactMatch( suffix2 ) || + alphaRx.exactMatch( suffix2 ) ) + return 1; // rc > than all the others + else + return QString::compare( suffix1, suffix2 ); + } + + else if( preRx.exactMatch( suffix1 ) ) { + int v1 = preRx.cap(1).toInt(); + + if( rcRx.exactMatch( suffix2 ) ) { + return -1; // pre is less than rc + } + else if( preRx.exactMatch( suffix2 ) ) { + int v2 = preRx.cap(1).toInt(); + return ( v1 == v2 ? 0 : ( v1 < v2 ? -1 : 1 ) ); + } + else if( betaRx.exactMatch( suffix2 ) || + alphaRx.exactMatch( suffix2 ) ) + return 1; // pre is greater than beta or alpha + else + return QString::compare( suffix1, suffix2 ); + } + + else if( betaRx.exactMatch( suffix1 ) ) { + int v1 = betaRx.cap(1).toInt(); + + if( rcRx.exactMatch( suffix2 ) || + preRx.exactMatch( suffix2 ) ) + return -1; // beta is less than rc or pre + else if( betaRx.exactMatch( suffix2 ) ) { + int v2 = betaRx.cap(1).toInt(); + return ( v1 == v2 ? 0 : ( v1 < v2 ? -1 : 1 ) ); + } + else if( alphaRx.exactMatch( suffix2 ) ) + return 1; // beta is greater then alpha + else + return QString::compare( suffix1, suffix2 ); + } + + else if( alphaRx.exactMatch( suffix1 ) ) { + int v1 = alphaRx.cap(1).toInt(); + + if( rcRx.exactMatch( suffix2 ) || + preRx.exactMatch( suffix2 ) || + betaRx.exactMatch( suffix2 ) ) + return -1; // alpha is less than all the others + else if( alphaRx.exactMatch( suffix2 ) ) { + int v2 = alphaRx.cap(1).toInt(); + return ( v1 == v2 ? 0 : ( v1 < v2 ? -1 : 1 ) ); + } + else + return QString::compare( suffix1, suffix2 ); + } + + else + return QString::compare( suffix1, suffix2 ); +} + + +bool operator<( const K3bVersion& v1, const K3bVersion& v2 ) +{ + // both version objects need to be valid + + if( v1.majorVersion() == v2.majorVersion() ) { + + // 1 == 1.0 + if( ( v1.minorVersion() == v2.minorVersion() ) + || + ( v1.minorVersion() == -1 && v2.minorVersion() == 0 ) + || + ( v2.minorVersion() == -1 && v1.minorVersion() == 0 ) + ) + { + // 1.0 == 1.0.0 + if( ( v1.patchLevel() == v2.patchLevel() ) + || + ( v1.patchLevel() == -1 && v2.patchLevel() == 0 ) + || + ( v2.patchLevel() == -1 && v1.patchLevel() == 0 ) + ) + { + return K3bVersion::compareSuffix( v1.suffix(), v2.suffix() ) < 0; + } + else + return ( v1.patchLevel() < v2.patchLevel() ); + } + else + return ( v1.minorVersion() < v2.minorVersion() ); + } + else + return ( v1.majorVersion() < v2.majorVersion() ); +} + +bool operator>( const K3bVersion& v1, const K3bVersion& v2 ) +{ + return operator<( v2, v1 ); +} + + +bool operator==( const K3bVersion& v1, const K3bVersion& v2 ) +{ + return ( v1.majorVersion() == v2.majorVersion() && + v1.minorVersion() == v2.minorVersion() && + v1.patchLevel() == v2.patchLevel() && + K3bVersion::compareSuffix( v1.suffix(), v2.suffix() ) == 0 ); +} + + +bool operator<=( const K3bVersion& v1, const K3bVersion& v2 ) +{ + return ( operator<( v1, v2 ) || operator==( v1, v2 ) ); +} + +bool operator>=( const K3bVersion& v1, const K3bVersion& v2 ) +{ + return ( operator>( v1, v2 ) || operator==( v1, v2 ) ); +} diff --git a/libk3b/core/k3bversion.h b/libk3b/core/k3bversion.h new file mode 100644 index 0000000..a6e3aee --- /dev/null +++ b/libk3b/core/k3bversion.h @@ -0,0 +1,141 @@ +/* + * + * $Id: k3bversion.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_VERSION_H_ +#define _K3B_VERSION_H_ + +#include +#include "k3b_export.h" +/** + * \brief Representation of a version. + * + * K3bVersion represents a version consisting of a major version (accessible via majorVersion()), + * a minor version (accessible via minorVersion()), a patchLevel (accessible via patchLevel()), + * and a suffix (accessible via suffix()). + * + * The major version is mandatory while all other fields are optional (in case of the minor version + * and the patchlevel -1 means that the field is undefined). + * + * K3bVersion tries to treat version suffixes in an "intelligent" way to properly compare versions + * (see compareSuffix() for more details). + * + * K3bVersion may also be used everywhere a QString is needed as it automatically converts to a + * string representation using createVersionString(). + */ +class LIBK3B_EXPORT K3bVersion +{ + public: + /** + * construct an empty version object + * which is invalid + * @ see isValid() + */ + K3bVersion(); + + /** + * copy constructor + */ + K3bVersion( const K3bVersion& ); + + /** + * this constructor tries to parse the given version string + */ + K3bVersion( const QString& version ); + + /** + * sets the version and generates a version string from it + */ + K3bVersion( int majorVersion, int minorVersion, int pachlevel = -1, const QString& suffix = QString::null ); + + /** + * tries to parse the version string + * used by the constructor + */ + void setVersion( const QString& ); + + bool isValid() const; + + /** + * sets the version and generates a version string from it + * used by the constructor + * + * If minorVersion or pachlevel are -1 they will not be used when generating the version string. + */ + void setVersion( int majorVersion, int minorVersion = -1, int patchlevel = -1, const QString& suffix = QString::null ); + + const QString& versionString() const { return m_versionString; } + int majorVersion() const { return m_majorVersion; } + int minorVersion() const { return m_minorVersion; } + int patchLevel() const { return m_patchLevel; } + const QString& suffix() const { return m_suffix; } + + /** + * just to make it possible to use as a QString + */ + operator const QString& () const { return m_versionString; } + K3bVersion& operator=( const QString& v ); + + /** + * \return A new K3bVersion object which equals this one except that the suffix is empty. + */ + K3bVersion simplify() const; + + /** + * If minorVersion or pachlevel are -1 they will not be used when generating the version string. + * If minorVersion is -1 patchlevel will be ignored. + */ + static QString createVersionString( int majorVersion, + int minorVersion = -1, + int patchlevel = -1, + const QString& suffix = QString::null ); + + /** + * "Intelligent" comparison of two version suffixes. + * + * This method checks for the following types of suffixes and treats them in the + * following order: + * + * [empty prefix] > rcX > preX > betaX > alphaX = aX (where X is a number) + * + * Every other suffixes are compared alphanumerical. + * An empty prefix is always considered newer than an unknown non-emtpy suffix (e.g. not one of the above.) + * + * @return \li -1 if suffix1 is less than suffix2 + * \li 0 if suffix1 equals suffix2 (be aware that this is not the same as comparing to strings as + * alphaX equals aX in this case.) + * \li 1 if suffix1 is greater than suffix2 + */ + static int compareSuffix( const QString& suffix1, const QString& suffix2 ); + + private: + static void splitVersionString( const QString& s, int& num, QString& suffix ); + + QString m_versionString; + int m_majorVersion; + int m_minorVersion; + int m_patchLevel; + QString m_suffix; +}; + + +LIBK3B_EXPORT bool operator<( const K3bVersion& v1, const K3bVersion& v2 ); +LIBK3B_EXPORT bool operator>( const K3bVersion& v1, const K3bVersion& v2 ); +LIBK3B_EXPORT bool operator==( const K3bVersion& v1, const K3bVersion& v2 ); +LIBK3B_EXPORT bool operator<=( const K3bVersion& v1, const K3bVersion& v2 ); +LIBK3B_EXPORT bool operator>=( const K3bVersion& v1, const K3bVersion& v2 ); + + +#endif diff --git a/libk3b/dummy.cpp b/libk3b/dummy.cpp new file mode 100644 index 0000000..9f6c7b2 --- /dev/null +++ b/libk3b/dummy.cpp @@ -0,0 +1 @@ +/* dummy file to have anything around.*/ diff --git a/libk3b/jobs/Makefile.am b/libk3b/jobs/Makefile.am new file mode 100644 index 0000000..72a9eac --- /dev/null +++ b/libk3b/jobs/Makefile.am @@ -0,0 +1,43 @@ +AM_CPPFLAGS = -I$(srcdir)/../core \ + -I$(srcdir)/../../libk3bdevice \ + -I$(srcdir)/../../src \ + -I$(srcdir)/../tools \ + -I$(srcdir)/../cddb \ + -I$(srcdir)/../plugin \ + -I$(srcdir)/../projects \ + -I$(srcdir)/../videodvd \ + -I$(srcdir)/../projects/audiocd \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libjobs.la + +if include_videodvdrip +libjobs_la_SOURCES = k3bdatatrackreader.cpp k3breadcdreader.cpp \ + k3bcdcopyjob.cpp k3bclonejob.cpp k3baudiosessionreadingjob.cpp \ + k3bdvdcopyjob.cpp k3bvideodvdtitletranscodingjob.cpp k3bvideodvdtitledetectclippingjob.cpp \ + k3baudiocuefilewritingjob.cpp k3bbinimagewritingjob.cpp \ + k3biso9660imagewritingjob.cpp \ + k3bdvdformattingjob.cpp k3bblankingjob.cpp k3bclonetocreader.cpp \ + k3bverificationjob.cpp + +include_HEADERS = k3bcdcopyjob.h k3bdvdcopyjob.h k3bclonejob.h \ + k3baudiocuefilewritingjob.h k3bbinimagewritingjob.h \ + k3biso9660imagewritingjob.h k3bdvdformattingjob.h \ + k3bblankingjob.h k3bvideodvdtitletranscodingjob.h k3bvideodvdtitledetectclippingjob.h \ + k3bverificationjob.h +else +libjobs_la_SOURCES = k3bdatatrackreader.cpp k3breadcdreader.cpp \ + k3bcdcopyjob.cpp k3bclonejob.cpp k3baudiosessionreadingjob.cpp \ + k3bdvdcopyjob.cpp \ + k3baudiocuefilewritingjob.cpp k3bbinimagewritingjob.cpp \ + k3biso9660imagewritingjob.cpp \ + k3bdvdformattingjob.cpp k3bblankingjob.cpp k3bclonetocreader.cpp \ + k3bverificationjob.cpp + +include_HEADERS = k3bcdcopyjob.h k3bdvdcopyjob.h k3bclonejob.h \ + k3baudiocuefilewritingjob.h k3bbinimagewritingjob.h \ + k3biso9660imagewritingjob.h k3bdvdformattingjob.h \ + k3bblankingjob.h k3bverificationjob.h +endif diff --git a/libk3b/jobs/k3baudiocuefilewritingjob.cpp b/libk3b/jobs/k3baudiocuefilewritingjob.cpp new file mode 100644 index 0000000..0c5cd9a --- /dev/null +++ b/libk3b/jobs/k3baudiocuefilewritingjob.cpp @@ -0,0 +1,272 @@ +/* + * + * $Id: k3baudiocuefilewritingjob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudiocuefilewritingjob.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +class K3bAudioCueFileWritingJob::AnalyserThread : public K3bThread +{ +public: + AnalyserThread() + : K3bThread() { + } + + void setDecoder( K3bAudioDecoder* dec ) { m_decoder = dec; } + +protected: + void run() { + emitStarted(); + m_decoder->analyseFile(); + emitFinished(true); + } + +private: + K3bAudioDecoder* m_decoder; +}; + + +K3bAudioCueFileWritingJob::K3bAudioCueFileWritingJob( K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bBurnJob( jh, parent, name ), + m_decoder(0) +{ + m_analyserThread = new AnalyserThread(); + m_analyserJob = new K3bThreadJob( m_analyserThread, this, this ); + connect( m_analyserJob, SIGNAL(finished(bool)), this, SLOT(slotAnalyserThreadFinished(bool)) ); + + m_audioDoc = new K3bAudioDoc( this ); + m_audioDoc->newDocument(); + m_audioJob = new K3bAudioJob( m_audioDoc, this, this ); + + // just loop all through + connect( m_audioJob, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) ); + connect( m_audioJob, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_audioJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + connect( m_audioJob, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_audioJob, SIGNAL(finished(bool)), this, SIGNAL(finished(bool)) ); + connect( m_audioJob, SIGNAL(canceled()), this, SIGNAL(canceled()) ); + connect( m_audioJob, SIGNAL(percent(int)), this, SIGNAL(percent(int)) ); + connect( m_audioJob, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); + connect( m_audioJob, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( m_audioJob, SIGNAL(processedSubSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( m_audioJob, SIGNAL(burning(bool)), this, SIGNAL(burning(bool)) ); + connect( m_audioJob, SIGNAL(bufferStatus(int)), this, SIGNAL(bufferStatus(int)) ); + connect( m_audioJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); + connect( m_audioJob, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + + m_canceled = false; + m_audioJobRunning = false; +} + + +K3bAudioCueFileWritingJob::~K3bAudioCueFileWritingJob() +{ + // the threadjob does not delete the thread + delete m_analyserThread; +} + + +K3bDevice::Device* K3bAudioCueFileWritingJob::writer() const +{ + return m_audioDoc->burner(); +} + + +QString K3bAudioCueFileWritingJob::jobDescription() const +{ + return i18n("Writing Audio Cue File"); +} + + +QString K3bAudioCueFileWritingJob::jobDetails() const +{ + return m_cueFile.section( '/', -1 ); +} + + +void K3bAudioCueFileWritingJob::start() +{ + // FIXME: here we trust that a job won't be started twice :( + jobStarted(); + m_canceled = false; + m_audioJobRunning = false; + importCueInProject(); +} + + +void K3bAudioCueFileWritingJob::cancel() +{ + m_canceled = true; + + // the AudioJob cancel method is very stupid. It emits the canceled signal even if it was never running :( + if( m_audioJobRunning ) + m_audioJob->cancel(); + m_analyserJob->cancel(); +} + + +void K3bAudioCueFileWritingJob::setCueFile( const QString& s ) +{ + m_cueFile = s; +} + + +void K3bAudioCueFileWritingJob::setOnTheFly( bool b ) +{ + m_audioDoc->setOnTheFly( b ); +} + + +void K3bAudioCueFileWritingJob::setSpeed( int s ) +{ + m_audioDoc->setSpeed( s ); +} + + +void K3bAudioCueFileWritingJob::setBurnDevice( K3bDevice::Device* dev ) +{ + m_audioDoc->setBurner( dev ); +} + + +void K3bAudioCueFileWritingJob::setWritingMode( int mode ) +{ + m_audioDoc->setWritingMode( mode ); +} + + +void K3bAudioCueFileWritingJob::setSimulate( bool b ) +{ + m_audioDoc->setDummy( b ); +} + + +void K3bAudioCueFileWritingJob::setCopies( int c ) +{ + m_audioDoc->setCopies( c ); +} + + +void K3bAudioCueFileWritingJob::setTempDir( const QString& s ) +{ + m_audioDoc->setTempDir( s ); +} + + +void K3bAudioCueFileWritingJob::slotAnalyserThreadFinished( bool ) +{ + if( !m_canceled ) { + if( m_audioDoc->lastTrack()->length() == 0 ) { + emit infoMessage( i18n("Analysing the audio file failed. Corrupt file?"), ERROR ); + jobFinished(false); + } + else { + // FIXME: m_audioJobRunning is never reset + m_audioJobRunning = true; + m_audioJob->start(); // from here on the audio job takes over completely + } + } + else { + emit canceled(); + jobFinished(false); + } +} + + +void K3bAudioCueFileWritingJob::importCueInProject() +{ + // cleanup the project (this wil also delete the decoder) + // we do not use newDocument as that would overwrite the settings already made + while( m_audioDoc->firstTrack() ) + delete m_audioDoc->firstTrack()->take(); + + m_decoder = 0; + + K3bCueFileParser parser( m_cueFile ); + if( parser.isValid() && parser.toc().contentType() == K3bDevice::AUDIO ) { + + kdDebug() << "(K3bAudioCueFileWritingJob::importCueFile) parsed with image: " << parser.imageFilename() << endl; + + // global cd-text + m_audioDoc->setTitle( parser.cdText().title() ); + m_audioDoc->setPerformer( parser.cdText().performer() ); + m_audioDoc->writeCdText( !parser.cdText().title().isEmpty() ); + + m_decoder = K3bAudioDecoderFactory::createDecoder( parser.imageFilename() ); + if( m_decoder ) { + m_decoder->setFilename( parser.imageFilename() ); + + K3bAudioTrack* after = 0; + K3bAudioFile* newFile = 0; + unsigned int i = 0; + for( K3bDevice::Toc::const_iterator it = parser.toc().begin(); + it != parser.toc().end(); ++it ) { + const K3bDevice::Track& track = *it; + + newFile = new K3bAudioFile( m_decoder, m_audioDoc ); + newFile->setStartOffset( track.firstSector() ); + newFile->setEndOffset( track.lastSector()+1 ); + + K3bAudioTrack* newTrack = new K3bAudioTrack( m_audioDoc ); + newTrack->addSource( newFile ); + newTrack->moveAfter( after ); + + // cd-text + newTrack->setTitle( parser.cdText()[i].title() ); + newTrack->setPerformer( parser.cdText()[i].performer() ); + + // add the next track after this one + after = newTrack; + ++i; + } + + // let the last source use the data up to the end of the file + if( newFile ) + newFile->setEndOffset(0); + + // now analyze the source + emit newTask( i18n("Analysing the audio file") ); + emit newSubTask( i18n("Analysing %1").arg( parser.imageFilename() ) ); + + // start the analyser thread + m_analyserThread->setDecoder( m_decoder ); + m_analyserJob->start(); + } + else { + emit infoMessage( i18n("Unable to handle '%1' due to an unsupported format.").arg( m_cueFile ), ERROR ); + jobFinished(false); + } + } + else { + emit infoMessage( i18n("No valid audio cue file: '%1'").arg( m_cueFile ), ERROR ); + jobFinished(false); + } +} + +#include "k3baudiocuefilewritingjob.moc" diff --git a/libk3b/jobs/k3baudiocuefilewritingjob.h b/libk3b/jobs/k3baudiocuefilewritingjob.h new file mode 100644 index 0000000..6e0a3c2 --- /dev/null +++ b/libk3b/jobs/k3baudiocuefilewritingjob.h @@ -0,0 +1,79 @@ +/* + * + * $Id: k3baudiocuefilewritingjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_CUE_FILEWRITING_JOB_H_ +#define _K3B_AUDIO_CUE_FILEWRITING_JOB_H_ + +#include +#include "k3b_export.h" +class K3bAudioDoc; +class K3bAudioJob; +class K3bAudioDecoder; +class K3bThreadJob; +namespace K3bDevice { + class Device; +} + + +class LIBK3B_EXPORT K3bAudioCueFileWritingJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bAudioCueFileWritingJob( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bAudioCueFileWritingJob(); + + K3bDevice::Device* writer() const; + + QString jobDescription() const; + QString jobDetails() const; + + const QString& cueFile() const { return m_cueFile; } + + public slots: + void start(); + void cancel(); + + void setCueFile( const QString& ); + void setSpeed( int s ); + void setBurnDevice( K3bDevice::Device* dev ); + void setWritingMode( int mode ); + void setSimulate( bool b ); + void setCopies( int c ); + void setOnTheFly( bool b ); + void setTempDir( const QString& ); + + private slots: + void slotAnalyserThreadFinished(bool); + + private: + void importCueInProject(); + + K3bDevice::Device* m_device; + + QString m_cueFile; + K3bAudioDoc* m_audioDoc; + K3bAudioJob* m_audioJob; + K3bAudioDecoder* m_decoder; + + bool m_canceled; + bool m_audioJobRunning; + + class AnalyserThread; + AnalyserThread* m_analyserThread; + K3bThreadJob* m_analyserJob; +}; + +#endif diff --git a/libk3b/jobs/k3baudiosessionreadingjob.cpp b/libk3b/jobs/k3baudiosessionreadingjob.cpp new file mode 100644 index 0000000..f4ac550 --- /dev/null +++ b/libk3b/jobs/k3baudiosessionreadingjob.cpp @@ -0,0 +1,278 @@ +/* + * + * $Id: k3baudiosessionreadingjob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudiosessionreadingjob.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +class K3bAudioSessionReadingJob::WorkThread : public K3bThread +{ +public: + WorkThread(); + ~WorkThread(); + + void init(); + void run(); + void cancel(); + + bool canceled; + + int fd; + K3bCdparanoiaLib* paranoia; + K3bDevice::Device* device; + K3bDevice::Toc toc; + K3bWaveFileWriter* waveFileWriter; + QStringList filenames; + int paranoiaMode; + int retries; + bool neverSkip; +}; + + +K3bAudioSessionReadingJob::WorkThread::WorkThread() + : K3bThread(), + fd(-1), + paranoia(0), + waveFileWriter(0), + paranoiaMode(0), + retries(50), + neverSkip(false) +{ +} + + +K3bAudioSessionReadingJob::WorkThread::~WorkThread() +{ + delete waveFileWriter; + delete paranoia; +} + + +void K3bAudioSessionReadingJob::WorkThread::init() +{ + canceled = false; +} + + +void K3bAudioSessionReadingJob::WorkThread::run() +{ + if( !paranoia ) + paranoia = K3bCdparanoiaLib::create(); + + if( !paranoia ) { + emitInfoMessage( i18n("Could not load libcdparanoia."), K3bJob::ERROR ); + emitFinished(false); + return; + } + + if( toc.isEmpty() ) + toc = device->readToc(); + + if( !paranoia->initParanoia( device, toc ) ) { + emitInfoMessage( i18n("Could not open device %1").arg(device->blockDeviceName()), + K3bJob::ERROR ); + emitFinished(false); + return; + } + + if( !paranoia->initReading() ) { + emitInfoMessage( i18n("Error while initializing audio ripping."), K3bJob::ERROR ); + emitFinished(false); + return; + } + + device->block( true ); + + // init settings + paranoia->setMaxRetries( retries ); + paranoia->setParanoiaMode( paranoiaMode ); + paranoia->setNeverSkip( neverSkip ); + + bool writeError = false; + unsigned int trackNum = 1; + unsigned int currentTrack = 0; + unsigned long trackRead = 0; + unsigned long totalRead = 0; + unsigned int lastTrackPercent = 0; + unsigned int lastTotalPercent = 0; + bool newTrack = true; + int status = 0; + char* buffer = 0; + while( !canceled && (buffer = paranoia->read( &status, &trackNum, fd == -1 /*when writing to a wav be want little endian */ )) ) { + + if( currentTrack != trackNum ) { + emitNextTrack( trackNum, paranoia->toc().count() ); + trackRead = 0; + lastTrackPercent = 0; + + currentTrack = trackNum; + newTrack = true; + } + + if( fd > 0 ) { + if( ::write( fd, buffer, CD_FRAMESIZE_RAW ) != CD_FRAMESIZE_RAW ) { + kdDebug() << "(K3bAudioSessionCopyJob::WorkThread) error while writing to fd " << fd << endl; + writeError = true; + break; + } + } + else { + if( newTrack ) { + newTrack = false; + + if( !waveFileWriter ) + waveFileWriter = new K3bWaveFileWriter(); + + if( filenames.count() < currentTrack ) { + kdDebug() << "(K3bAudioSessionCopyJob) not enough image filenames given: " << currentTrack << endl; + writeError = true; + break; + } + + if( !waveFileWriter->open( filenames[currentTrack-1] ) ) { + emitInfoMessage( i18n("Unable to open '%1' for writing.").arg(filenames[currentTrack-1]), K3bJob::ERROR ); + writeError = true; + break; + } + } + + waveFileWriter->write( buffer, + CD_FRAMESIZE_RAW, + K3bWaveFileWriter::LittleEndian ); + } + + trackRead++; + totalRead++; + + unsigned int trackPercent = 100 * trackRead / toc[currentTrack-1].length().lba(); + if( trackPercent > lastTrackPercent ) { + lastTrackPercent = trackPercent; + emitSubPercent( lastTrackPercent ); + } + unsigned int totalPercent = 100 * totalRead / paranoia->rippedDataLength(); + if( totalPercent > lastTotalPercent ) { + lastTotalPercent = totalPercent; + emitPercent( lastTotalPercent ); + } + } + + if( waveFileWriter ) + waveFileWriter->close(); + + paranoia->close(); + + device->block( false ); + + if( status != K3bCdparanoiaLib::S_OK ) { + emitInfoMessage( i18n("Unrecoverable error while ripping track %1.").arg(trackNum), K3bJob::ERROR ); + emitFinished(false); + return; + } + + emitFinished( !writeError & !canceled ); +} + + +void K3bAudioSessionReadingJob::WorkThread::cancel() +{ + canceled = true; + // FIXME: add backup killing like in the audio ripping and make sure to close paranoia +} + + + + +K3bAudioSessionReadingJob::K3bAudioSessionReadingJob( K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bThreadJob( jh, parent, name ) +{ + m_thread = new WorkThread(); + setThread( m_thread ); +} + + +K3bAudioSessionReadingJob::~K3bAudioSessionReadingJob() +{ + delete m_thread; +} + + +void K3bAudioSessionReadingJob::setDevice( K3bDevice::Device* dev ) +{ + m_thread->device = dev; + m_thread->toc = K3bDevice::Toc(); +} + + +void K3bAudioSessionReadingJob::setToc( const K3bDevice::Toc& toc ) +{ + m_thread->toc = toc; +} + + +void K3bAudioSessionReadingJob::writeToFd( int fd ) +{ + m_thread->fd = fd; +} + +void K3bAudioSessionReadingJob::setImageNames( const QStringList& l ) +{ + m_thread->filenames = l; + m_thread->fd = -1; +} + + +void K3bAudioSessionReadingJob::setParanoiaMode( int m ) +{ + m_thread->paranoiaMode = m; +} + + +void K3bAudioSessionReadingJob::setReadRetries( int r ) +{ + m_thread->retries = r; +} + +void K3bAudioSessionReadingJob::setNeverSkip( bool b ) +{ + m_thread->neverSkip = b; +} + + +void K3bAudioSessionReadingJob::start() +{ + k3bcore->blockDevice( m_thread->device ); + K3bThreadJob::start(); +} + + +void K3bAudioSessionReadingJob::cleanupJob( bool success ) +{ + Q_UNUSED( success ); + k3bcore->unblockDevice( m_thread->device ); +} + +#include "k3baudiosessionreadingjob.moc" diff --git a/libk3b/jobs/k3baudiosessionreadingjob.h b/libk3b/jobs/k3baudiosessionreadingjob.h new file mode 100644 index 0000000..21f3d50 --- /dev/null +++ b/libk3b/jobs/k3baudiosessionreadingjob.h @@ -0,0 +1,75 @@ +/* + * + * $Id: k3baudiosessionreadingjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIOSESSION_READING_JOB_H_ +#define _K3B_AUDIOSESSION_READING_JOB_H_ + +#include + +#include + + +namespace K3bDevice { + class Device; + class Toc; +} + + +class K3bAudioSessionReadingJob : public K3bThreadJob +{ + Q_OBJECT + + public: + K3bAudioSessionReadingJob( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bAudioSessionReadingJob(); + + /** + * For now this simply reads all the audio tracks at the beginning + * since we only support CD-Extra mixed mode cds. + */ + void setDevice( K3bDevice::Device* ); + + /** + * Use for faster initialization + */ + void setToc( const K3bDevice::Toc& toc ); + + /** + * the data gets written directly into fd instead of imagefiles. + * To disable just set fd to -1 (the default) + */ + void writeToFd( int fd ); + + /** + * Used if fd == -1 + */ + void setImageNames( const QStringList& l ); + + void setParanoiaMode( int m ); + void setReadRetries( int ); + void setNeverSkip( bool b ); + + public slots: + void start(); + + protected: + void cleanupJob( bool success ); + + private: + class WorkThread; + WorkThread* m_thread; +}; + +#endif diff --git a/libk3b/jobs/k3bbinimagewritingjob.cpp b/libk3b/jobs/k3bbinimagewritingjob.cpp new file mode 100644 index 0000000..de76e3f --- /dev/null +++ b/libk3b/jobs/k3bbinimagewritingjob.cpp @@ -0,0 +1,234 @@ +/* + * + * $Id: k3bbinimagewritingjob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Klaus-Dieter Krannich + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bbinimagewritingjob.h" +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + + +K3bBinImageWritingJob::K3bBinImageWritingJob( K3bJobHandler* hdl, QObject* parent ) + : K3bBurnJob( hdl, parent ), + m_device(0), + m_simulate(false), + m_force(false), + m_noFix(false), + m_tocFile(0), + m_speed(2), + m_copies(1), + m_writer(0) +{ +} + +K3bBinImageWritingJob::~K3bBinImageWritingJob() +{ +} + +void K3bBinImageWritingJob::start() +{ + m_canceled = false; + + if( m_copies < 1 ) + m_copies = 1; + m_finishedCopies = 0; + + jobStarted(); + emit newTask( i18n("Write Binary Image") ); + + if( prepareWriter() ) + writerStart(); + else + cancel(); + +} + +void K3bBinImageWritingJob::cancel() +{ + m_canceled = true; + m_writer->cancel(); + emit canceled(); + jobFinished( false ); +} + +bool K3bBinImageWritingJob::prepareWriter() +{ + if( m_writer ) + delete m_writer; + + int usedWritingApp = writingApp(); + const K3bExternalBin* cdrecordBin = k3bcore->externalBinManager()->binObject("cdrecord"); + if( usedWritingApp == K3b::CDRECORD || + ( usedWritingApp == K3b::DEFAULT && cdrecordBin && cdrecordBin->hasFeature("cuefile") && m_device->dao() ) ) { + usedWritingApp = K3b::CDRECORD; + + // IMPROVEME: check if it's a cdrdao toc-file + if( m_tocFile.right(4) == ".toc" ) { + kdDebug() << "(K3bBinImageWritingJob) imagefile has ending toc." << endl; + usedWritingApp = K3b::CDRDAO; + } + else { + // TODO: put this into K3bCueFileParser + // TODO: check K3bCueFileParser::imageFilenameInCue() + // let's see if cdrecord can handle the cue file + QFile f( m_tocFile ); + if( f.open( IO_ReadOnly ) ) { + QTextStream fStr( &f ); + if( fStr.read().contains( "MODE1/2352" ) ) { + kdDebug() << "(K3bBinImageWritingJob) cuefile contains MODE1/2352 track. using cdrdao." << endl; + usedWritingApp = K3b::CDRDAO; + } + f.close(); + } + else + kdDebug() << "(K3bBinImageWritingJob) could not open file " << m_tocFile << endl; + } + } + else + usedWritingApp = K3b::CDRDAO; + + if( usedWritingApp == K3b::CDRECORD ) { + // create cdrecord job + K3bCdrecordWriter* writer = new K3bCdrecordWriter( m_device, this ); + + writer->setDao( true ); + writer->setSimulate( m_simulate ); + writer->setBurnSpeed( m_speed ); + writer->setCueFile ( m_tocFile ); + + if( m_noFix ) { + writer->addArgument("-multi"); + } + + if( m_force ) { + writer->addArgument("-force"); + } + + m_writer = writer; + } + else { + // create cdrdao job + K3bCdrdaoWriter* writer = new K3bCdrdaoWriter( m_device, this ); + writer->setCommand( K3bCdrdaoWriter::WRITE ); + writer->setSimulate( m_simulate ); + writer->setBurnSpeed( m_speed ); + writer->setForce( m_force ); + + // multisession + writer->setMulti( m_noFix ); + + writer->setTocFile( m_tocFile ); + + m_writer = writer; + } + + connect( m_writer, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_writer, SIGNAL(percent(int)), this, SLOT(copyPercent(int)) ); + connect( m_writer, SIGNAL(subPercent(int)), this, SLOT(copySubPercent(int)) ); + connect( m_writer, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSize(int, int)) ); + connect( m_writer, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) ); + connect( m_writer, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); + connect( m_writer, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + connect( m_writer, SIGNAL(finished(bool)), this, SLOT(writerFinished(bool)) ); + connect( m_writer, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) ); + connect( m_writer, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_writer, SIGNAL(nextTrack(int, int)), this, SLOT(slotNextTrack(int, int)) ); + connect( m_writer, SIGNAL(debuggingOutput(const QString&, const QString&)), this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + + return true; +} + + +void K3bBinImageWritingJob::writerStart() +{ + + if( waitForMedia( m_device ) < 0 ) { + cancel(); + } + // just to be sure we did not get canceled during the async discWaiting + else if( !m_canceled ) { + emit burning(true); + m_writer->start(); + } +} + +void K3bBinImageWritingJob::copyPercent(int p) +{ + emit percent( (100*m_finishedCopies + p)/m_copies ); +} + +void K3bBinImageWritingJob::copySubPercent(int p) +{ + emit subPercent(p); +} + +void K3bBinImageWritingJob::writerFinished(bool ok) +{ + if( m_canceled ) + return; + + if (ok) { + m_finishedCopies++; + if ( m_finishedCopies == m_copies ) { + emit infoMessage( i18n("%n copy successfully created", "%n copies successfully created", m_copies),K3bJob::INFO ); + jobFinished( true ); + } + else { + writerStart(); + } + } + else { + jobFinished(false); + } +} + + +void K3bBinImageWritingJob::slotNextTrack( int t, int tt ) +{ + emit newSubTask( i18n("Writing track %1 of %2").arg(t).arg(tt) ); +} + + +QString K3bBinImageWritingJob::jobDescription() const +{ + return ( i18n("Writing cue/bin Image") + + ( m_copies > 1 + ? i18n(" - %n Copy", " - %n Copies", m_copies) + : QString::null ) ); +} + + +QString K3bBinImageWritingJob::jobDetails() const +{ + return m_tocFile.section("/", -1); +} + + +void K3bBinImageWritingJob::setTocFile(const QString& s) +{ + m_tocFile = s; +} + +#include "k3bbinimagewritingjob.moc" diff --git a/libk3b/jobs/k3bbinimagewritingjob.h b/libk3b/jobs/k3bbinimagewritingjob.h new file mode 100644 index 0000000..3666793 --- /dev/null +++ b/libk3b/jobs/k3bbinimagewritingjob.h @@ -0,0 +1,79 @@ +/* + * + * $Id$ + * Copyright (C) 2003 Klaus-Dieter Krannich + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BBINIMAGEWRITINGJOB_H +#define K3BBINIMAGEWRITINGJOB_H + +#include +#include "k3b_export.h" +class K3bAbstractWriter; +namespace K3bDevice { + class Device; +} + +/** + *@author Klaus-Dieter Krannich + */ +class LIBK3B_EXPORT K3bBinImageWritingJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bBinImageWritingJob( K3bJobHandler*, QObject* parent = 0 ); + ~K3bBinImageWritingJob(); + + K3bDevice::Device* writer() const { return m_device; }; + + QString jobDescription() const; + QString jobDetails() const; + + public slots: + void start(); + void cancel(); + + void setWriter( K3bDevice::Device* dev ) { m_device = dev; } + void setSimulate( bool b ) { m_simulate = b; } + void setForce(bool b) { m_force = b; } + void setMulti( bool b ) { m_noFix = b; } + void setTocFile( const QString& s); + void setCopies(int c) { m_copies = c; } + void setSpeed( int s ) { m_speed = s; } + + private slots: + void writerFinished(bool); + void copyPercent(int p); + void copySubPercent(int p); + void slotNextTrack( int, int ); + + private: + void writerStart(); + bool prepareWriter(); + + K3bDevice::Device* m_device; + bool m_simulate; + bool m_force; + bool m_noFix; + QString m_tocFile; + int m_speed; + int m_copies; + int m_finishedCopies; + + bool m_canceled; + + K3bAbstractWriter* m_writer; +}; + +#endif diff --git a/libk3b/jobs/k3bblankingjob.cpp b/libk3b/jobs/k3bblankingjob.cpp new file mode 100644 index 0000000..c11f4b4 --- /dev/null +++ b/libk3b/jobs/k3bblankingjob.cpp @@ -0,0 +1,176 @@ +/* + * + * $Id: k3bblankingjob.cpp 630823 2007-02-06 14:07:10Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bblankingjob.h" +#include "k3bcdrecordwriter.h" +#include "k3bcdrdaowriter.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + + +K3bBlankingJob::K3bBlankingJob( K3bJobHandler* hdl, QObject* parent ) + : K3bBurnJob( hdl, parent ), + m_writerJob(0), + m_force(true), + m_device(0), + m_speed(0), + m_mode(Fast), + m_writingApp(K3b::DEFAULT), + m_canceled(false), + m_forceNoEject(false) +{ +} + + +K3bBlankingJob::~K3bBlankingJob() +{ + delete m_writerJob; +} + + +K3bDevice::Device* K3bBlankingJob::writer() const +{ + return m_device; +} + + +void K3bBlankingJob::setDevice( K3bDevice::Device* dev ) +{ + m_device = dev; +} + + +void K3bBlankingJob::start() +{ + if( m_device == 0 ) + return; + + jobStarted(); + + slotStartErasing(); +} + +void K3bBlankingJob::slotStartErasing() +{ + m_canceled = false; + + if( m_writerJob ) + delete m_writerJob; + + if( m_writingApp == K3b::CDRDAO ) { + K3bCdrdaoWriter* writer = new K3bCdrdaoWriter( m_device, this ); + m_writerJob = writer; + + writer->setCommand(K3bCdrdaoWriter::BLANK); + writer->setBlankMode( m_mode == Fast ? K3bCdrdaoWriter::MINIMAL : K3bCdrdaoWriter::FULL ); + writer->setForce(m_force); + writer->setBurnSpeed(m_speed); + writer->setForceNoEject( m_forceNoEject ); + } + else { + K3bCdrecordWriter* writer = new K3bCdrecordWriter( m_device, this ); + m_writerJob = writer; + + QString mode; + switch( m_mode ) { + case Fast: + mode = "fast"; + break; + case Complete: + mode = "all"; + break; + case Track: + mode = "track"; + break; + case Unclose: + mode = "unclose"; + break; + case Session: + mode = "session"; + break; + } + + writer->addArgument("blank="+ mode); + + if (m_force) + writer->addArgument("-force"); + writer->setBurnSpeed(m_speed); + writer->setForceNoEject( m_forceNoEject ); + } + + connect(m_writerJob, SIGNAL(finished(bool)), this, SLOT(slotFinished(bool))); + connect(m_writerJob, SIGNAL(infoMessage( const QString&, int)), + this,SIGNAL(infoMessage( const QString&, int))); + connect( m_writerJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + + if( waitForMedia( m_device, + K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE, + K3bDevice::MEDIA_CD_RW, + i18n("Please insert a rewritable CD medium into drive

%1 %2 (%3).") + .arg(m_device->vendor()) + .arg(m_device->description()) + .arg(m_device->devicename()) ) < 0 ) { + emit canceled(); + jobFinished(false); + return; + } + + m_writerJob->start(); +} + + +void K3bBlankingJob::cancel() +{ + m_canceled = true; + + if( m_writerJob ) + m_writerJob->cancel(); +} + + +void K3bBlankingJob::slotFinished(bool success) +{ + if( success ) { + emit infoMessage( i18n("Process completed successfully"), K3bJob::SUCCESS ); + jobFinished( true ); + } + else { + if( m_canceled ) { + emit infoMessage( i18n("Canceled."), ERROR ); + emit canceled(); + } + else { + emit infoMessage( i18n("Blanking error "), K3bJob::ERROR ); + emit infoMessage( i18n("Sorry, no error handling yet."), K3bJob::ERROR ); + } + jobFinished( false ); + } +} + + + +#include "k3bblankingjob.moc" diff --git a/libk3b/jobs/k3bblankingjob.h b/libk3b/jobs/k3bblankingjob.h new file mode 100644 index 0000000..8cfe0a1 --- /dev/null +++ b/libk3b/jobs/k3bblankingjob.h @@ -0,0 +1,71 @@ +/* + * + * $Id: k3bblankingjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_BLANKING_JOB_H +#define K3B_BLANKING_JOB_H + +#include +#include "k3b_export.h" +class KProcess; +class QString; +class K3bDevice::Device; +class K3bAbstractWriter; + + +class LIBK3B_EXPORT K3bBlankingJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bBlankingJob( K3bJobHandler*, QObject* parent = 0 ); + ~K3bBlankingJob(); + + K3bDevice::Device* writer() const; + + bool hasBeenCanceled() const { return m_canceled; } + + enum blank_mode { Fast, Complete, Track, Unclose, Session }; + + public slots: + void start(); + void cancel(); + void setForce( bool f ) { m_force = f; } + void setDevice( K3bDevice::Device* d ); + void setSpeed( int s ) { m_speed = s; } + void setMode( int m ) { m_mode = m; } + void setWritingApp (int app) { m_writingApp = app; } + + /** + * If set true the job ignores the global K3b setting + * and does not eject the CD-RW after finishing + */ + void setForceNoEject( bool b ) { m_forceNoEject = b; } + + private slots: + void slotFinished(bool); + void slotStartErasing(); + + private: + K3bAbstractWriter* m_writerJob; + bool m_force; + K3bDevice::Device* m_device; + int m_speed; + int m_mode; + int m_writingApp; + bool m_canceled; + bool m_forceNoEject; +}; + +#endif diff --git a/libk3b/jobs/k3bcdcopyjob.cpp b/libk3b/jobs/k3bcdcopyjob.cpp new file mode 100644 index 0000000..ff8f35d --- /dev/null +++ b/libk3b/jobs/k3bcdcopyjob.cpp @@ -0,0 +1,1213 @@ +/* + * + * $Id.cpp,v 1.82 2005/02/04 09:27:19 trueg Exp $ + * Copyright (C) 2003-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bcdcopyjob.h" +#include "k3baudiosessionreadingjob.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class K3bCdCopyJob::Private +{ +public: + Private() + : canceled(false), + running(false), + readcdReader(0), + dataTrackReader(0), + audioSessionReader(0), + cdrecordWriter(0), + infFileWriter(0), + cddb(0) { + } + + bool canceled; + bool error; + bool readingSuccessful; + bool running; + + unsigned int numSessions; + bool doNotCloseLastSession; + + unsigned int doneCopies; + unsigned int currentReadSession; + unsigned int currentWrittenSession; + + K3bDevice::Toc toc; + QByteArray cdTextRaw; + + K3bReadcdReader* readcdReader; + K3bDataTrackReader* dataTrackReader; + K3bAudioSessionReadingJob* audioSessionReader; + K3bCdrecordWriter* cdrecordWriter; + K3bInfFileWriter* infFileWriter; + + bool audioReaderRunning; + bool dataReaderRunning; + bool writerRunning; + + // image filenames, one for every track + QStringList imageNames; + + // inf-filenames for writing audio tracks + QStringList infNames; + + // indicates if we created a dir or not + bool deleteTempDir; + + K3bCddb* cddb; + K3bCddbResultEntry cddbInfo; + + bool haveCddb; + bool haveCdText; + + QValueVector dataSessionProbablyTAORecorded; + + // used to determine progress + QValueVector sessionSizes; + long overallSize; +}; + + +K3bCdCopyJob::K3bCdCopyJob( K3bJobHandler* hdl, QObject* parent ) + : K3bBurnJob( hdl, parent ), + m_simulate(false), + m_copies(1), + m_onlyCreateImages(false), + m_onTheFly(true), + m_ignoreDataReadErrors(false), + m_ignoreAudioReadErrors(true), + m_noCorrection(false), + m_dataReadRetries(128), + m_audioReadRetries(5), + m_preferCdText(false), + m_copyCdText(true), + m_writingMode( K3b::WRITING_MODE_AUTO ) +{ + d = new Private(); +} + + +K3bCdCopyJob::~K3bCdCopyJob() +{ + delete d->infFileWriter; + delete d; +} + + +void K3bCdCopyJob::start() +{ + d->running = true; + d->canceled = false; + d->error = false; + d->readingSuccessful = false; + d->audioReaderRunning = d->dataReaderRunning = d->writerRunning = false; + d->sessionSizes.clear(); + d->dataSessionProbablyTAORecorded.clear(); + d->deleteTempDir = false; + d->haveCdText = false; + d->haveCddb = false; + + jobStarted(); + + emit newTask( i18n("Checking Source Medium") ); + + emit burning(false); + emit newSubTask( i18n("Waiting for source medium") ); + + // wait for a source disk + if( waitForMedia( m_readerDevice, + K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE, + K3bDevice::MEDIA_WRITABLE_CD|K3bDevice::MEDIA_CD_ROM ) < 0 ) { + finishJob( true, false ); + return; + } + + emit newSubTask( i18n("Checking source medium") ); + + // FIXME: read ISRCs and MCN + + connect( K3bDevice::diskInfo( m_readerDevice ), SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, SLOT(slotDiskInfoReady(K3bDevice::DeviceHandler*)) ); +} + + +void K3bCdCopyJob::slotDiskInfoReady( K3bDevice::DeviceHandler* dh ) +{ + if( dh->success() ) { + d->toc = dh->toc(); + + // + // for now we copy audio, pure data (aka 1 data track), cd-extra (2 session, audio and data), + // and data multisession which one track per session. + // Everything else will be rejected + // + bool canCopy = true; + bool audio = false; + d->numSessions = dh->diskInfo().numSessions(); + d->doNotCloseLastSession = (dh->diskInfo().diskState() == K3bDevice::STATE_INCOMPLETE); + switch( dh->toc().contentType() ) { + case K3bDevice::DATA: + // check if every track is in it's own session + // only then we copy the cd + if( (int)dh->toc().count() != dh->diskInfo().numSessions() ) { + emit infoMessage( i18n("K3b does not copy CDs containing multiple data tracks."), ERROR ); + canCopy = false; + } + else if( dh->diskInfo().numSessions() > 1 ) + emit infoMessage( i18n("Copying Multisession Data CD."), INFO ); + else + emit infoMessage( i18n("Copying Data CD."), INFO ); + break; + + case K3bDevice::MIXED: + audio = true; + if( dh->diskInfo().numSessions() != 2 || d->toc[0].type() != K3bDevice::Track::AUDIO ) { + emit infoMessage( i18n("K3b can only copy CD-Extra mixed mode CDs."), ERROR ); + canCopy = false; + } + else + emit infoMessage( i18n("Copying Enhanced Audio CD (CD-Extra)."), INFO ); + break; + + case K3bDevice::AUDIO: + audio = true; + emit infoMessage( i18n("Copying Audio CD."), INFO ); + break; + + case K3bDevice::NONE: + default: + emit infoMessage( i18n("The source disk is empty."), ERROR ); + canCopy = false; + break; + } + + // + // A data track recorded in TAO mode has two run-out blocks which cannot be read and contain + // zero data anyway. The problem is that I do not know of a valid method to determine if a track + // was written in TAO (the control nibble does definitely not work, I never saw one which did not + // equal 4). + // So the solution for now is to simply try to read the last sector of a data track. If this is not + // possible we assume it was written in TAO mode and reduce the length by 2 sectors + // + unsigned char buffer[2048]; + int i = 1; + for( K3bDevice::Toc::iterator it = d->toc.begin(); it != d->toc.end(); ++it ) { + if( (*it).type() == K3bDevice::Track::DATA ) { + // we try twice just to be sure + if( m_readerDevice->read10( buffer, 2048, (*it).lastSector().lba(), 1 ) || + m_readerDevice->read10( buffer, 2048, (*it).lastSector().lba(), 1 ) ) { + d->dataSessionProbablyTAORecorded.append(false); + kdDebug() << "(K3bCdCopyJob) track " << i << " probably DAO recorded." << endl; + } + else { + d->dataSessionProbablyTAORecorded.append(true); + kdDebug() << "(K3bCdCopyJob) track " << i << " probably TAO recorded." << endl; + } + } + + ++i; + } + + + // + // To copy mode2 data tracks we need cdrecord >= 2.01a12 which introduced the -xa1 and -xamix options + // + if( k3bcore->externalBinManager()->binObject("cdrecord") && + !k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "xamix" ) ) { + for( K3bDevice::Toc::const_iterator it = d->toc.begin(); it != d->toc.end(); ++it ) { + if( (*it).type() == K3bDevice::Track::DATA && + ( (*it).mode() == K3bDevice::Track::XA_FORM1 || + (*it).mode() == K3bDevice::Track::XA_FORM2 ) ) { + emit infoMessage( i18n("K3b needs cdrecord 2.01a12 or newer to copy Mode2 data tracks."), ERROR ); + finishJob( true, false ); + return; + } + } + } + + + // + // It is not possible to create multisession cds in raw writing mode + // + if( d->numSessions > 1 && m_writingMode == K3b::RAW ) { + if( !questionYesNo( i18n("You will only be able to copy the first session in raw writing mode. " + "Continue anyway?"), + i18n("Multisession CD") ) ) { + finishJob( true, false ); + return; + } + else { + emit infoMessage( i18n("Only copying first session."), WARNING ); + // TODO: remove the second session from the progress stuff + } + } + + + // + // We already create the temp filenames here since we need them to check the free space + // + if( !m_onTheFly || m_onlyCreateImages ) { + if( !prepareImageFiles() ) { + finishJob( false, true ); + return; + } + + // + // check free temp space + // + KIO::filesize_t imageSpaceNeeded = 0; + for( K3bDevice::Toc::const_iterator it = d->toc.begin(); it != d->toc.end(); ++it ) { + if( (*it).type() == K3bDevice::Track::AUDIO ) + imageSpaceNeeded += (*it).length().audioBytes() + 44; + else + imageSpaceNeeded += (*it).length().mode1Bytes(); + } + + unsigned long avail, size; + QString pathToTest = m_tempPath.left( m_tempPath.findRev( '/' ) ); + if( !K3b::kbFreeOnFs( pathToTest, size, avail ) ) { + emit infoMessage( i18n("Unable to determine free space in temporary directory '%1'.").arg(pathToTest), ERROR ); + d->error = true; + canCopy = false; + } + else { + if( avail < imageSpaceNeeded/1024 ) { + emit infoMessage( i18n("Not enough space left in temporary directory."), ERROR ); + d->error = true; + canCopy = false; + } + } + } + + if( canCopy ) { + if( K3b::isMounted( m_readerDevice ) ) { + emit infoMessage( i18n("Unmounting source medium"), INFO ); + K3b::unmount( m_readerDevice ); + } + + d->overallSize = 0; + + // now create some progress helper values + for( K3bDevice::Toc::const_iterator it = d->toc.begin(); it != d->toc.end(); ++it ) { + d->overallSize += (*it).length().lba(); + if( d->sessionSizes.isEmpty() || (*it).type() == K3bDevice::Track::DATA ) + d->sessionSizes.append( (*it).length().lba() ); + else + d->sessionSizes[0] += (*it).length().lba(); + } + + if( audio && !m_onlyCreateImages ) { + if( m_copyCdText ) + searchCdText(); + else + queryCddb(); + } + else + startCopy(); + } + else { + finishJob( false, true ); + } + } + else { + emit infoMessage( i18n("Unable to read TOC"), ERROR ); + finishJob( false, true ); + } +} + + +void K3bCdCopyJob::searchCdText() +{ + emit newSubTask( i18n("Searching CD-TEXT") ); + + connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::CD_TEXT_RAW, m_readerDevice ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotCdTextReady(K3bDevice::DeviceHandler*)) ); +} + + +void K3bCdCopyJob::slotCdTextReady( K3bDevice::DeviceHandler* dh ) +{ + if( dh->success() ) { + if( K3bDevice::CdText::checkCrc( dh->cdTextRaw() ) ) { + K3bDevice::CdText cdt( dh->cdTextRaw() ); + emit infoMessage( i18n("Found CD-TEXT (%1 - %2).").arg(cdt.performer()).arg(cdt.title()), SUCCESS ); + d->haveCdText = true; + d->cdTextRaw = dh->cdTextRaw(); + } + else { + emit infoMessage( i18n("Found corrupted CD-TEXT. Ignoring it."), WARNING ); + d->haveCdText = false; + } + + if( d->haveCdText && m_preferCdText ) + startCopy(); + else + queryCddb(); + } + else { + emit infoMessage( i18n("No CD-TEXT found."), INFO ); + + d->haveCdText = false; + + queryCddb(); + } +} + + +void K3bCdCopyJob::queryCddb() +{ + emit newSubTask( i18n("Querying Cddb") ); + + d->haveCddb = false; + + if( !d->cddb ) { + d->cddb = new K3bCddb( this ); + connect( d->cddb, SIGNAL(queryFinished(int)), + this, SLOT(slotCddbQueryFinished(int)) ); + } + + KConfig* c = k3bcore->config(); + c->setGroup("Cddb"); + + d->cddb->readConfig( c ); + d->cddb->query( d->toc ); +} + + +void K3bCdCopyJob::slotCddbQueryFinished( int error ) +{ + if( error == K3bCddbQuery::SUCCESS ) { + d->cddbInfo = d->cddb->result(); + d->haveCddb = true; + + emit infoMessage( i18n("Found Cddb entry (%1 - %2).").arg(d->cddbInfo.cdArtist).arg(d->cddbInfo.cdTitle), SUCCESS ); + + // save the entry locally + KConfig* c = k3bcore->config(); + c->setGroup( "Cddb" ); + if( c->readBoolEntry( "save cddb entries locally", true ) ) + d->cddb->saveEntry( d->cddbInfo ); + } + else if( error == K3bCddbQuery::NO_ENTRY_FOUND ) { + emit infoMessage( i18n("No Cddb entry found."), WARNING ); + } + else { + emit infoMessage( i18n("Cddb error (%1).").arg(d->cddb->errorString()), ERROR ); + } + + startCopy(); +} + + +void K3bCdCopyJob::startCopy() +{ + d->currentWrittenSession = d->currentReadSession = 1; + d->doneCopies = 0; + + if( m_onTheFly ) { + emit newSubTask( i18n("Preparing write process...") ); + + if( writeNextSession() ) + readNextSession(); + else { + finishJob( d->canceled, d->error ); + } + } + else + readNextSession(); +} + + +void K3bCdCopyJob::cancel() +{ + d->canceled = true; + + if( d->writerRunning ) { + // + // we will handle cleanup in slotWriterFinished() + // if we are writing onthefly the reader won't be able to write + // anymore and will finish unsuccessfully, too + // + d->cdrecordWriter->cancel(); + } + else if( d->audioReaderRunning ) + d->audioSessionReader->cancel(); + else if( d->dataReaderRunning ) + // d->readcdReader->cancel(); + d->dataTrackReader->cancel(); +} + + +bool K3bCdCopyJob::prepareImageFiles() +{ + kdDebug() << "(K3bCdCopyJob) prepareImageFiles()" << endl; + + d->imageNames.clear(); + d->infNames.clear(); + d->deleteTempDir = false; + + QFileInfo fi( m_tempPath ); + + if( d->toc.count() > 1 || d->toc.contentType() == K3bDevice::AUDIO ) { + // create a directory which contains all the images and inf and stuff + // and save it in some cool structure + + bool tempDirReady = false; + if( !fi.isDir() ) { + if( QFileInfo( m_tempPath.section( '/', 0, -2 ) ).isDir() ) { + if( !QFile::exists( m_tempPath ) ) { + QDir dir( m_tempPath.section( '/', 0, -2 ) ); + dir.mkdir( m_tempPath.section( '/', -1 ) ); + tempDirReady = true; + } + else + m_tempPath = m_tempPath.section( '/', 0, -2 ); + } + else { + emit infoMessage( i18n("Specified an unusable temporary path. Using default."), WARNING ); + m_tempPath = K3b::defaultTempPath(); + } + } + + // create temp dir + if( !tempDirReady ) { + QDir dir( m_tempPath ); + m_tempPath = K3b::findUniqueFilePrefix( "k3bCdCopy", m_tempPath ); + kdDebug() << "(K3bCdCopyJob) creating temp dir: " << m_tempPath << endl; + if( !dir.mkdir( m_tempPath, true ) ) { + emit infoMessage( i18n("Unable to create temporary directory '%1'.").arg(m_tempPath), ERROR ); + return false; + } + d->deleteTempDir = true; + } + + m_tempPath = K3b::prepareDir( m_tempPath ); + emit infoMessage( i18n("Using temporary directory %1.").arg(m_tempPath), INFO ); + + // create temp filenames + int i = 1; + for( K3bDevice::Toc::const_iterator it = d->toc.begin(); it != d->toc.end(); ++it ) { + if( (*it).type() == K3bDevice::Track::AUDIO ) { + d->imageNames.append( m_tempPath + QString("Track%1.wav").arg(QString::number(i).rightJustify(2, '0')) ); + d->infNames.append( m_tempPath + QString("Track%1.inf").arg(QString::number(i).rightJustify(2, '0')) ); + } + else + d->imageNames.append( m_tempPath + QString("Track%1.iso").arg(QString::number(i).rightJustify(2, '0')) ); + ++i; + } + + kdDebug() << "(K3bCdCopyJob) created image filenames:" << endl; + for( unsigned int i = 0; i < d->imageNames.count(); ++i ) + kdDebug() << "(K3bCdCopyJob) " << d->imageNames[i] << endl; + + return true; + } + else { + // we only need a single image file + if( !fi.isFile() || + questionYesNo( i18n("Do you want to overwrite %1?").arg(m_tempPath), + i18n("File Exists") ) ) { + if( fi.isDir() ) + m_tempPath = K3b::findTempFile( "iso", m_tempPath ); + else if( !QFileInfo( m_tempPath.section( '/', 0, -2 ) ).isDir() ) { + emit infoMessage( i18n("Specified an unusable temporary path. Using default."), WARNING ); + m_tempPath = K3b::findTempFile( "iso" ); + } + // else the user specified a file in an existing dir + + emit infoMessage( i18n("Writing image file to %1.").arg(m_tempPath), INFO ); + } + else + return false; + + d->imageNames.append( m_tempPath ); + + return true; + } +} + + +void K3bCdCopyJob::readNextSession() +{ + if( !m_onTheFly || m_onlyCreateImages ) { + if( d->numSessions > 1 ) + emit newTask( i18n("Reading Session %1").arg(d->currentReadSession) ); + else + emit newTask( i18n("Reading Source Medium") ); + + if( d->currentReadSession == 1 ) + emit newSubTask( i18n("Reading track %1 of %2").arg(1).arg(d->toc.count()) ); + } + + // there is only one situation where we need the audiosessionreader: + // if the first session is an audio session. That means the first track + // is an audio track + if( d->currentReadSession == 1 && d->toc[0].type() == K3bDevice::Track::AUDIO ) { + if( !d->audioSessionReader ) { + d->audioSessionReader = new K3bAudioSessionReadingJob( this, this ); + connect( d->audioSessionReader, SIGNAL(nextTrack(int, int)), + this, SLOT(slotReadingNextTrack(int, int)) ); + connectSubJob( d->audioSessionReader, + SLOT(slotSessionReaderFinished(bool)), + true, + SLOT(slotReaderProgress(int)), + SLOT(slotReaderSubProgress(int)) ); + } + + d->audioSessionReader->setDevice( m_readerDevice ); + d->audioSessionReader->setToc( d->toc ); + d->audioSessionReader->setParanoiaMode( m_paranoiaMode ); + d->audioSessionReader->setReadRetries( m_audioReadRetries ); + d->audioSessionReader->setNeverSkip( !m_ignoreAudioReadErrors ); + if( m_onTheFly ) + d->audioSessionReader->writeToFd( d->cdrecordWriter->fd() ); + else + d->audioSessionReader->setImageNames( d->imageNames ); // the audio tracks are always the first tracks + + d->audioReaderRunning = true; + d->audioSessionReader->start(); + } + else { + if( !d->dataTrackReader ) { + d->dataTrackReader = new K3bDataTrackReader( this, this ); + connect( d->dataTrackReader, SIGNAL(percent(int)), this, SLOT(slotReaderProgress(int)) ); + connect( d->dataTrackReader, SIGNAL(processedSize(int, int)), this, SLOT(slotReaderProcessedSize(int, int)) ); + connect( d->dataTrackReader, SIGNAL(finished(bool)), this, SLOT(slotSessionReaderFinished(bool)) ); + connect( d->dataTrackReader, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( d->dataTrackReader, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + } + + d->dataTrackReader->setDevice( m_readerDevice ); + d->dataTrackReader->setIgnoreErrors( m_ignoreDataReadErrors ); + d->dataTrackReader->setNoCorrection( m_noCorrection ); + d->dataTrackReader->setRetries( m_dataReadRetries ); + if( m_onlyCreateImages ) + d->dataTrackReader->setSectorSize( K3bDataTrackReader::MODE1 ); + else + d->dataTrackReader->setSectorSize( K3bDataTrackReader::AUTO ); + + K3bTrack* track = 0; + unsigned int dataTrackIndex = 0; + if( d->toc.contentType() == K3bDevice::MIXED ) { + track = &d->toc[d->toc.count()-1]; + dataTrackIndex = 0; + } + else { + track = &d->toc[d->currentReadSession-1]; // only one track per session + dataTrackIndex = d->currentReadSession-1; + } + + // HACK: if the track is TAO recorded cut the two run-out sectors + if( d->dataSessionProbablyTAORecorded.count() > dataTrackIndex && + d->dataSessionProbablyTAORecorded[dataTrackIndex] ) + d->dataTrackReader->setSectorRange( track->firstSector(), track->lastSector() - 2 ); + else + d->dataTrackReader->setSectorRange( track->firstSector(), track->lastSector() ); + + int trackNum = d->currentReadSession; + if( d->toc.contentType() == K3bDevice::MIXED ) + trackNum = d->toc.count(); + + if( m_onTheFly ) + d->dataTrackReader->writeToFd( d->cdrecordWriter->fd() ); + else + d->dataTrackReader->setImagePath( d->imageNames[trackNum-1] ); + + d->dataReaderRunning = true; + if( !m_onTheFly || m_onlyCreateImages ) + slotReadingNextTrack( 1, 1 ); + + d->dataTrackReader->start(); + } +} + + +bool K3bCdCopyJob::writeNextSession() +{ + // we emit our own task since the cdrecord task is way too simple + if( d->numSessions > 1 ) { + if( m_simulate ) + emit newTask( i18n("Simulating Session %1").arg(d->currentWrittenSession) ); + else if( m_copies > 1 ) + emit newTask( i18n("Writing Copy %1 (Session %2)").arg(d->doneCopies+1).arg(d->currentWrittenSession) ); + else + emit newTask( i18n("Writing Copy (Session %2)").arg(d->currentWrittenSession) ); + } + else { + if( m_simulate ) + emit newTask( i18n("Simulating") ); + else if( m_copies > 1 ) + emit newTask( i18n("Writing Copy %1").arg(d->doneCopies+1) ); + else + emit newTask( i18n("Writing Copy") ); + } + + emit newSubTask( i18n("Waiting for media") ); + + // if session > 1 we wait for an appendable CD + if( waitForMedia( m_writerDevice, + d->currentWrittenSession > 1 && !m_simulate + ? K3bDevice::STATE_INCOMPLETE + : K3bDevice::STATE_EMPTY, + K3bDevice::MEDIA_WRITABLE_CD ) < 0 ) { + + finishJob( true, false ); + return false; + } + + if( !d->cdrecordWriter ) { + d->cdrecordWriter = new K3bCdrecordWriter( m_writerDevice, this, this ); + connect( d->cdrecordWriter, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( d->cdrecordWriter, SIGNAL(percent(int)), this, SLOT(slotWriterProgress(int)) ); + connect( d->cdrecordWriter, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSize(int, int)) ); + connect( d->cdrecordWriter, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); + connect( d->cdrecordWriter, SIGNAL(processedSubSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( d->cdrecordWriter, SIGNAL(nextTrack(int, int)), this, SLOT(slotWritingNextTrack(int, int)) ); + connect( d->cdrecordWriter, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) ); + connect( d->cdrecordWriter, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); + connect( d->cdrecordWriter, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + connect( d->cdrecordWriter, SIGNAL(finished(bool)), this, SLOT(slotWriterFinished(bool)) ); + // connect( d->cdrecordWriter, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) ); + connect( d->cdrecordWriter, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( d->cdrecordWriter, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + } + + d->cdrecordWriter->setBurnDevice( m_writerDevice ); + d->cdrecordWriter->clearArguments(); + d->cdrecordWriter->setSimulate( m_simulate ); + d->cdrecordWriter->setBurnSpeed( m_speed ); + + + // create the cdrecord arguments + if( d->currentWrittenSession == 1 && d->toc[0].type() == K3bDevice::Track::AUDIO ) { + // + // Audio session + // + + + if( !d->infFileWriter ) + d->infFileWriter = new K3bInfFileWriter(); + + // + // create the inf files if not already done + // + if( d->infNames.isEmpty() || !QFile::exists( d->infNames[0] ) ) { + + unsigned int trackNumber = 1; + + for( K3bDevice::Toc::const_iterator it = d->toc.begin(); it != d->toc.end(); ++it ) { + const K3bDevice::Track& track = *it; + + if( track.type() == K3bDevice::Track::DATA ) + break; + + d->infFileWriter->setTrack( track ); + d->infFileWriter->setTrackNumber( trackNumber ); + + if( d->haveCddb ) { + d->infFileWriter->setTrackTitle( d->cddbInfo.titles[trackNumber-1] ); + d->infFileWriter->setTrackPerformer( d->cddbInfo.artists[trackNumber-1] ); + d->infFileWriter->setTrackMessage( d->cddbInfo.extInfos[trackNumber-1] ); + + d->infFileWriter->setAlbumTitle( d->cddbInfo.cdTitle ); + d->infFileWriter->setAlbumPerformer( d->cddbInfo.cdArtist ); + } + + if( m_onTheFly ) { + + d->infFileWriter->setBigEndian( true ); + + // we let KTempFile choose a temp file but delete it on our own + // the same way we delete them when writing with images + // It is important that the files have the ending inf because + // cdrecord only checks this + + KTempFile tmp( QString::null, ".inf" ); + d->infNames.append( tmp.name() ); + bool success = d->infFileWriter->save( *tmp.textStream() ); + tmp.close(); + if( !success ) + return false; + } + else { + d->infFileWriter->setBigEndian( false ); + + if( !d->infFileWriter->save( d->infNames[trackNumber-1] ) ) + return false; + } + + ++trackNumber; + } + } + + // + // the inf files are ready and named correctly when writing with images + // + int usedWritingMode = m_writingMode; + if( usedWritingMode == K3b::WRITING_MODE_AUTO ) { + // + // there are a lot of writers out there which produce coasters + // in dao mode if the CD contains pregaps of length 0 (or maybe already != 2 secs?) + // + bool zeroPregap = false; + if( d->numSessions == 1 ) { + for( K3bDevice::Toc::const_iterator it = d->toc.begin(); it != d->toc.end(); ++it ) { + const K3bDevice::Track& track = *it; + if( track.index0() == 0 ) { + ++it; + if( it != d->toc.end() ) + zeroPregap = true; + --it; + } + } + } + + if( zeroPregap && m_writerDevice->supportsRawWriting() ) { + if( d->numSessions == 1 ) + usedWritingMode = K3b::RAW; + else + usedWritingMode = K3b::TAO; + } + else if( m_writerDevice->dao() ) + usedWritingMode = K3b::DAO; + else if( m_writerDevice->supportsRawWriting() ) + usedWritingMode = K3b::RAW; + else + usedWritingMode = K3b::TAO; + } + d->cdrecordWriter->setWritingMode( usedWritingMode ); + + if( d->numSessions > 1 ) + d->cdrecordWriter->addArgument( "-multi" ); + + if( d->haveCddb || d->haveCdText ) { + if( usedWritingMode == K3b::TAO ) { + emit infoMessage( i18n("It is not possible to write CD-Text in TAO mode."), WARNING ); + } + else if( d->haveCdText && ( !d->haveCddb || m_preferCdText ) ) { + // use the raw CDTEXT data + d->cdrecordWriter->setRawCdText( d->cdTextRaw ); + } + else { + // make sure the writer job does not create raw cdtext + d->cdrecordWriter->setRawCdText( QByteArray() ); + // cdrecord will use the cdtext data in the inf files + d->cdrecordWriter->addArgument( "-text" ); + } + } + + d->cdrecordWriter->addArgument( "-useinfo" ); + + // + // add all the audio tracks + // + d->cdrecordWriter->addArgument( "-audio" )->addArgument( "-shorttrack" ); + + for( unsigned int i = 0; i < d->infNames.count(); ++i ) { + if( m_onTheFly ) + d->cdrecordWriter->addArgument( d->infNames[i] ); + else + d->cdrecordWriter->addArgument( d->imageNames[i] ); + } + } + else { + // + // Data Session + // + K3bTrack* track = 0; + unsigned int dataTrackIndex = 0; + if( d->toc.contentType() == K3bDevice::MIXED ) { + track = &d->toc[d->toc.count()-1]; + dataTrackIndex = 0; + } + else { + track = &d->toc[d->currentWrittenSession-1]; + dataTrackIndex = d->currentWrittenSession-1; + } + + bool multi = d->doNotCloseLastSession || (d->numSessions > 1 && d->currentWrittenSession < d->toc.count()); + int usedWritingMode = m_writingMode; + if( usedWritingMode == K3b::WRITING_MODE_AUTO ) { + // at least the NEC3540a does write 2056 byte sectors only in tao mode. Same for LG4040b + // since writing data tracks in TAO mode is no loss let's default to TAO in the case of 2056 byte + // sectors (which is when writing xa form1 sectors here) + if( m_writerDevice->dao() && + d->toc.count() == 1 && + !multi && + track->mode() == K3bDevice::Track::MODE1 ) + usedWritingMode = K3b::DAO; + else + usedWritingMode = K3b::TAO; + } + d->cdrecordWriter->setWritingMode( usedWritingMode ); + + // + // all but the last session of a multisession disk are written in multi mode + // and every data track has it's own session which we forced above + // + if( multi ) + d->cdrecordWriter->addArgument( "-multi" ); + + // just to let the reader init + if( m_onTheFly ) + d->cdrecordWriter->addArgument( "-waiti" ); + + if( track->mode() == K3bDevice::Track::MODE1 ) + d->cdrecordWriter->addArgument( "-data" ); + else if( track->mode() == K3bDevice::Track::XA_FORM1 ) + d->cdrecordWriter->addArgument( "-xa1" ); + else + d->cdrecordWriter->addArgument( "-xamix" ); + + if( m_onTheFly ) { + // HACK: if the track is TAO recorded cut the two run-out sectors + unsigned long trackLen = track->length().lba(); + if( d->dataSessionProbablyTAORecorded.count() > dataTrackIndex && + d->dataSessionProbablyTAORecorded[dataTrackIndex] ) + trackLen -= 2; + + if( track->mode() == K3bDevice::Track::MODE1 ) + trackLen = trackLen * 2048; + else if( track->mode() == K3bDevice::Track::XA_FORM1 ) + trackLen = trackLen * 2056; // see k3bdatatrackreader.h + else + trackLen = trackLen * 2332; // see k3bdatatrackreader.h + d->cdrecordWriter->addArgument( QString("-tsize=%1").arg(trackLen) )->addArgument("-"); + } + else if( d->toc.contentType() == K3bDevice::MIXED ) + d->cdrecordWriter->addArgument( d->imageNames[d->toc.count()-1] ); + else + d->cdrecordWriter->addArgument( d->imageNames[d->currentWrittenSession-1] ); + + // clear cd text from previous sessions + d->cdrecordWriter->setRawCdText( QByteArray() ); + } + + + // + // Finally start the writer + // + emit burning(true); + d->writerRunning = true; + d->cdrecordWriter->start(); + + return true; +} + + +// both the readcdreader and the audiosessionreader are connected to this slot +void K3bCdCopyJob::slotSessionReaderFinished( bool success ) +{ + d->audioReaderRunning = d->dataReaderRunning = false; + + if( success ) { + if( d->numSessions > 1 ) + emit infoMessage( i18n("Successfully read session %1.").arg(d->currentReadSession), SUCCESS ); + else + emit infoMessage( i18n("Successfully read source disk."), SUCCESS ); + + if( !m_onTheFly ) { + if( d->numSessions > d->currentReadSession ) { + d->currentReadSession++; + readNextSession(); + } + else { + d->readingSuccessful = true; + if( !m_onlyCreateImages ) { + if( m_readerDevice == m_writerDevice ) { + // eject the media (we do this blocking to know if it worked + // becasue if it did not it might happen that k3b overwrites a CD-RW + // source) + if( !m_readerDevice->eject() ) { + blockingInformation( i18n("K3b was unable to eject the source disk. Please do so manually.") ); + } + } + + if( !writeNextSession() ) { + // nothing is running here... + finishJob( d->canceled, d->error ); + } + } + else { + finishJob( false, false ); + } + } + } + } + else { + if( !d->canceled ) { + emit infoMessage( i18n("Error while reading session %1.").arg(d->currentReadSession), ERROR ); + if( m_onTheFly ) + d->cdrecordWriter->setSourceUnreadable(true); + } + + finishJob( d->canceled, !d->canceled ); + } +} + + +void K3bCdCopyJob::slotWriterFinished( bool success ) +{ + emit burning(false); + + d->writerRunning = false; + + if( success ) { + // + // if this was the last written session we need to reset d->currentWrittenSession + // and start a new writing if more copies are wanted + // + + if( d->currentWrittenSession < d->numSessions ) { + d->currentWrittenSession++; + d->currentReadSession++; + + // reload the media + emit newSubTask( i18n("Reloading the medium") ); + connect( K3bDevice::reload( m_writerDevice ), SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, SLOT(slotMediaReloadedForNextSession(K3bDevice::DeviceHandler*)) ); + } + else { + d->doneCopies++; + + if( !m_simulate && d->doneCopies < m_copies ) { + // start next copy + K3bDevice::eject( m_writerDevice ); + + d->currentWrittenSession = 1; + d->currentReadSession = 1; + if( writeNextSession() ) { + if( m_onTheFly ) + readNextSession(); + } + else { + // nothing running here... + finishJob( d->canceled, d->error ); + } + } + else { + finishJob( false, false ); + } + } + } + else { + // + // If we are writing on the fly the reader will also stop when it is not able to write anymore + // The error handling will be done only here in that case + // + + // the K3bCdrecordWriter emitted an error message + + finishJob( d->canceled, !d->canceled ); + } +} + + +void K3bCdCopyJob::slotMediaReloadedForNextSession( K3bDevice::DeviceHandler* dh ) +{ + if( !dh->success() ) + blockingInformation( i18n("Please reload the medium and press 'ok'"), + i18n("Unable to close the tray") ); + + if( !writeNextSession() ) { + // nothing is running here... + finishJob( d->canceled, d->error ); + } + else if( m_onTheFly ) + readNextSession(); +} + + +void K3bCdCopyJob::cleanup() +{ + if( m_onTheFly || !m_keepImage || ((d->canceled || d->error) && !d->readingSuccessful) ) { + emit infoMessage( i18n("Removing temporary files."), INFO ); + for( QStringList::iterator it = d->infNames.begin(); it != d->infNames.end(); ++it ) + QFile::remove( *it ); + } + + if( !m_onTheFly && (!m_keepImage || ((d->canceled || d->error) && !d->readingSuccessful)) ) { + emit infoMessage( i18n("Removing image files."), INFO ); + for( QStringList::iterator it = d->imageNames.begin(); it != d->imageNames.end(); ++it ) + QFile::remove( *it ); + + // remove the tempdir created in prepareImageFiles() + if( d->deleteTempDir ) { + KIO::NetAccess::del( KURL::fromPathOrURL(m_tempPath), 0 ); + d->deleteTempDir = false; + } + } +} + + +void K3bCdCopyJob::slotReaderProgress( int p ) +{ + if( !m_onTheFly || m_onlyCreateImages ) { + int bigParts = ( m_onlyCreateImages ? 1 : (m_simulate ? 2 : m_copies + 1 ) ); + double done = (double)p * (double)d->sessionSizes[d->currentReadSession-1] / 100.0; + for( unsigned int i = 0; i < d->currentReadSession-1; ++i ) + done += (double)d->sessionSizes[i]; + emit percent( (int)(100.0*done/(double)d->overallSize/(double)bigParts) ); + + if( d->dataReaderRunning ) + emit subPercent(p); + } +} + + +void K3bCdCopyJob::slotReaderSubProgress( int p ) +{ + // only if reading an audiosession + if( !m_onTheFly || m_onlyCreateImages ) { + emit subPercent( p ); + } +} + + +void K3bCdCopyJob::slotReaderProcessedSize( int p, int pp ) +{ + if( !m_onTheFly ) + emit processedSubSize( p, pp ); +} + + +void K3bCdCopyJob::slotWriterProgress( int p ) +{ + int bigParts = ( m_simulate ? 1 : m_copies ) + ( m_onTheFly ? 0 : 1 ); + long done = ( m_onTheFly ? d->doneCopies : d->doneCopies+1 ) * d->overallSize + + (p * d->sessionSizes[d->currentWrittenSession-1] / 100); + for( unsigned int i = 0; i < d->currentWrittenSession-1; ++i ) + done += d->sessionSizes[i]; + emit percent( 100*done/d->overallSize/bigParts ); +} + + +void K3bCdCopyJob::slotWritingNextTrack( int t, int tt ) +{ + if( d->toc.contentType() == K3bDevice::MIXED ) { + if( d->currentWrittenSession == 1 ) + emit newSubTask( i18n("Writing track %1 of %2").arg(t).arg(d->toc.count()) ); + else + emit newSubTask( i18n("Writing track %1 of %2").arg(d->toc.count()).arg(d->toc.count()) ); + } + else if( d->numSessions > 1 ) + emit newSubTask( i18n("Writing track %1 of %2").arg(d->currentWrittenSession).arg(d->toc.count()) ); + else + emit newSubTask( i18n("Writing track %1 of %2").arg(t).arg(tt) ); +} + + +void K3bCdCopyJob::slotReadingNextTrack( int t, int ) +{ + if( !m_onTheFly || m_onlyCreateImages ) { + int track = t; + if( d->audioReaderRunning ) + track = t; + else if( d->toc.contentType() == K3bDevice::MIXED ) + track = d->toc.count(); + else + track = d->currentReadSession; + + emit newSubTask( i18n("Reading track %1 of %2").arg(track).arg(d->toc.count()) ); + } +} + + +QString K3bCdCopyJob::jobDescription() const +{ + if( m_onlyCreateImages ) { + return i18n("Creating CD Image"); + } + else if( m_simulate ) { + if( m_onTheFly ) + return i18n("Simulating CD Copy On-The-Fly"); + else + return i18n("Simulating CD Copy"); + } + else { + if( m_onTheFly ) + return i18n("Copying CD On-The-Fly"); + else + return i18n("Copying CD"); + } +} + + +QString K3bCdCopyJob::jobDetails() const +{ + return i18n("Creating 1 copy", + "Creating %n copies", + (m_simulate||m_onlyCreateImages) ? 1 : m_copies ); +} + + +void K3bCdCopyJob::finishJob( bool c, bool e ) +{ + if( d->running ) { + if( c ) { + d->canceled = true; + emit canceled(); + } + if( e ) + d->error = true; + + cleanup(); + + d->running = false; + + jobFinished( !(c||e) ); + } +} + +#include "k3bcdcopyjob.moc" diff --git a/libk3b/jobs/k3bcdcopyjob.h b/libk3b/jobs/k3bcdcopyjob.h new file mode 100644 index 0000000..3ab77e8 --- /dev/null +++ b/libk3b/jobs/k3bcdcopyjob.h @@ -0,0 +1,117 @@ +/* + * + * $Id: k3bcdcopyjob.h 690187 2007-07-20 09:18:03Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3BCDCOPYJOB_H_ +#define _K3BCDCOPYJOB_H_ + +#include +#include "k3b_export.h" + +namespace K3bDevice { + class Device; + class DeviceHandler; +} + + +/** + *@author Sebastian Trueg + */ +class LIBK3B_EXPORT K3bCdCopyJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bCdCopyJob( K3bJobHandler* hdl, QObject* parent = 0 ); + ~K3bCdCopyJob(); + + K3bDevice::Device* writer() const { return m_onlyCreateImages ? 0 : m_writerDevice; } + K3bDevice::Device* reader() const { return m_readerDevice; } + + QString jobDescription() const; + QString jobDetails() const; + + public slots: + void start(); + void cancel(); + + public: + void setWriterDevice( K3bDevice::Device* dev ) { m_writerDevice = dev; } + void setReaderDevice( K3bDevice::Device* dev ) { m_readerDevice = dev; } + void setWritingMode( int m ) { m_writingMode = m; } + void setSpeed( int s ) { m_speed = s; } + void setOnTheFly( bool b ) { m_onTheFly = b; } + void setKeepImage( bool b ) { m_keepImage = b; } + void setOnlyCreateImage( bool b ) { m_onlyCreateImages = b; } + void setSimulate( bool b ) { m_simulate = b; } + void setTempPath( const QString& path ) { m_tempPath= path; } + void setCopies( unsigned int c ) { m_copies = c; } + void setParanoiaMode( int i ) { m_paranoiaMode = i; } + void setIgnoreDataReadErrors( bool b ) { m_ignoreDataReadErrors = b; } + void setDataReadRetries( int i ) { m_dataReadRetries = i; } + void setIgnoreAudioReadErrors( bool b ) { m_ignoreAudioReadErrors = b; } + void setAudioReadRetries( int i ) { m_audioReadRetries = i; } + void setPreferCdText( bool b ) { m_preferCdText = b; } + void setCopyCdText( bool b ) { m_copyCdText = b; } + void setNoCorrection( bool b ) { m_noCorrection = b; } + + private slots: + void slotDiskInfoReady( K3bDevice::DeviceHandler* ); + void slotCdTextReady( K3bDevice::DeviceHandler* ); + void slotMediaReloadedForNextSession( K3bDevice::DeviceHandler* dh ); + void slotCddbQueryFinished(int); + void slotWritingNextTrack( int t, int tt ); + void slotReadingNextTrack( int t, int tt ); + void slotSessionReaderFinished( bool success ); + void slotWriterFinished( bool success ); + void slotReaderProgress( int p ); + void slotReaderSubProgress( int p ); + void slotWriterProgress( int p ); + void slotReaderProcessedSize( int p, int pp ); + + private: + void startCopy(); + void searchCdText(); + void queryCddb(); + bool writeNextSession(); + void readNextSession(); + bool prepareImageFiles(); + void cleanup(); + void finishJob( bool canceled, bool error ); + + K3bDevice::Device* m_writerDevice; + K3bDevice::Device* m_readerDevice; + bool m_simulate; + int m_speed; + int m_paranoiaMode; + unsigned int m_copies; + bool m_keepImage; + bool m_onlyCreateImages; + bool m_onTheFly; + bool m_ignoreDataReadErrors; + bool m_ignoreAudioReadErrors; + bool m_noCorrection; + int m_dataReadRetries; + int m_audioReadRetries; + bool m_preferCdText; + bool m_copyCdText; + QString m_tempPath; + int m_writingMode; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/jobs/k3bcdda2wavreader.cpp b/libk3b/jobs/k3bcdda2wavreader.cpp new file mode 100644 index 0000000..3df87d3 --- /dev/null +++ b/libk3b/jobs/k3bcdda2wavreader.cpp @@ -0,0 +1,254 @@ +/* + * + * $Id: k3bcdda2wavreader.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bcdda2wavreader.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +class K3bCdda2wavReader::Private +{ +public: + Private() + : cdda2wavBin(0), + process(0), + cancaled(false), + running(false), + fdToWriteTo(-1) { + } + + const K3bExternalBin* cdda2wavBin; + K3bProcess* process; + + bool cancaled; + bool running; + + int fdToWriteTo; + + int currentTrack; + QValueVector trackOffsets; +}; + + +K3bCdda2wavReader::K3bCdda2wavReader( QObject* parent, const char* name ) + : K3bJob( parent, name ) +{ + d = new Private(); +} + + +K3bCdda2wavReader::~K3bCdda2wavReader() +{ + delete d->process; + delete d; +} + + +bool K3bCdda2wavReader::active() const +{ + return d->running; +} + + +void K3bCdda2wavReader::writeToFd( int fd ) +{ + d->fdToWriteTo = fd; +} + + +void K3bCdda2wavReader::start() +{ + start( false ); +} + + +void K3bCdda2wavReader::start( bool onlyInfo ) +{ + d->running = true; + d->cancaled = false; + d->currentTrack = 1; + d->trackOffsets.clear(); + + jobStarted(); + + d->cdda2wavBin = k3bcore->externalBinManager()->binObject( "cdda2wav" ); + if( !d->cdda2wavBin ) { + emit infoMessage( i18n("Could not find %1 executable.").arg("cdda2wav"), ERROR ); + jobFinished(false); + d->running = false; + return; + } + + // prepare the process + delete d->process; + d->process = new K3bProcess(); + d->process->setSplitStdout(true); + d->process->setSuppressEmptyLines(true); + d->process->setWorkingDirectory( m_imagePath ); + connect( d->process, SIGNAL(stdoutLine(const QString&)), this, SLOT(slotProcessLine(const QString&)) ); + connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotProcessLine(const QString&)) ); + connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited(KProcess*)) ); + + // create the command line + *d->process << d->cdda2wavBin->path; + *d->process << "-vall" << ( d->cdda2wavBin->hasFeature( "gui" ) ? "-gui" : "-g" ); + if( d->cdda2wavBin->hasFeature( "dev" ) ) + *d->process << QString("dev=%1").arg(K3bDevice::externalBinDeviceParameter(m_device, d->cdda2wavBin)); + else + *d->process << "-D" << K3bDevice::externalBinDeviceParameter(m_device, d->cdda2wavBin); + *d->process << ( d->cdda2wavBin->hasFeature( "bulk" ) ? "-bulk" : "-B" ); + if( onlyInfo ) + *d->process << ( d->cdda2wavBin->hasFeature( "info-only" ) ? "-info-only" : "-J" ); + else if( d->fdToWriteTo != -1 ) + *d->process << ( d->cdda2wavBin->hasFeature( "no-infofile" ) ? "-no-infofile" : "-H" ); + + // additional user parameters from config + const QStringList& params = d->cdda2wavBin->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *d->process << *it; + + // start the thing + if( !d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) { + // something went wrong when starting the program + // it "should" be the executable + kdDebug() << "(K3bCdda2wavReader) could not start cdda2wav" << endl; + emit infoMessage( i18n("Could not start %1.").arg("cdda2wav"), K3bJob::ERROR ); + d->running = false; + jobFinished(false); + } +} + + +void K3bCdda2wavReader::cancel() +{ + if( d->running ) { + d->cancaled = true; + if( d->process ) + if( d->process->isRunning() ) + d->process->kill(); + } +} + + +void K3bCdda2wavReader::slotProcessLine( const QString& line ) +{ + // Tracks:11 44:37.30 + // CDINDEX discid: ZvzBXv614ACgzn1bWWy107cs0nA- + // CDDB discid: 0x8a0a730b + // CD-Text: not detected + // CD-Extra: not detected + // Album title: '' from '' + // T01: 0 3:39.70 audio linear copydenied stereo title '' from '' + // T02: 16495 3:10.47 audio linear copydenied stereo title '' from '' + // T03: 30792 3:30.00 audio linear copydenied stereo title '' from '' + // T04: 46542 4:05.05 audio linear copydenied stereo title '' from '' + // T05: 64922 3:44.35 audio linear copydenied stereo title '' from '' + // T06: 81757 4:36.45 audio linear copydenied stereo title '' from '' + // T07: 102502 3:59.30 audio linear copydenied stereo title '' from '' + // T08: 120457 5:24.30 audio linear copydenied stereo title '' from '' + // T09: 144787 3:26.28 audio linear copydenied stereo title '' from '' + // T10: 160265 4:07.20 audio linear copydenied stereo title '' from '' + // T11: 178810 4:51.20 audio linear copydenied stereo title '' from '' + + // percent_done: + // 100% track 1 successfully recorded + // 100% track 2 successfully recorded + // 100% track 3 successfully recorded + + + + static QRegExp rx( "T\\d\\d:" ); + if( rx.exactMatch( line.left(4) ) || line.startsWith( "Leadout" ) ) { + int pos = line.find( " " ); + int endpos = line.find( QRegExp( "\\d" ), pos ); + endpos = line.find( " ", endpos ); + bool ok; + int offset = line.mid( pos, endpos-pos ).toInt(&ok); + if( ok ) + d->trackOffsets.append( offset ); + else + kdDebug() << "(K3bCdda2wavReader) track offset parsing error: '" << line.mid( pos, endpos-pos ) << "'" << endl; + } + + else if( line.startsWith( "percent_done" ) ) { + // the reading starts + d->currentTrack = 1; + emit nextTrack( d->currentTrack, d->trackOffsets.count() ); + } + + else if( line.contains("successfully recorded") ) { + d->currentTrack++; + emit nextTrack( d->currentTrack, d->trackOffsets.count() ); + } + + else if( line.contains("%") ) { + // parse progress + bool ok; + int p = line.left(3).toInt(&ok); + if( ok ) { + emit subPercent( p ); + + int overall = d->trackOffsets[d->currentTrack-1]; + int tSize = d->trackOffsets[d->currentTrack] - d->trackOffsets[d->currentTrack-1]; + overall += (tSize*p/100); + + emit percent( overall*100/d->trackOffsets[d->trackOffsets.count()-1] ); + } + else + kdDebug() << "(K3bCdda2wavReader) track progress parsing error: '" << line.left(3) << "'" << endl; + } +} + + +void K3bCdda2wavReader::slotProcessExited( KProcess* p ) +{ + d->running = false; + + if( d->cancaled ) { + emit canceled(); + jobFinished(false); + return; + } + + if( p->normalExit() ) { + // TODO: improve this + + if( p->exitStatus() == 0 ) { + jobFinished( true ); + } + else { + emit infoMessage( i18n("%1 returned an unknown error (code %2).") + .arg("Cdda2wav").arg(p->exitStatus()), ERROR ); + jobFinished( false ); + } + } + else { + emit infoMessage( i18n("%1 did not exit cleanly.").arg("Cdda2wav"), + ERROR ); + jobFinished( false ); + } +} + +#include "k3bcdda2wavreader.moc" diff --git a/libk3b/jobs/k3bcdda2wavreader.h b/libk3b/jobs/k3bcdda2wavreader.h new file mode 100644 index 0000000..edde65c --- /dev/null +++ b/libk3b/jobs/k3bcdda2wavreader.h @@ -0,0 +1,70 @@ +/* + * + * $Id: k3bcdda2wavreader.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_CDDA2WAV_READER_H_ +#define _K3B_CDDA2WAV_READER_H_ + +#include + +class KProcess; +namespace K3bDevice { + class Device; +}; + + +/** + * An Audio CD reader completely based on cdda2wav. + * It does not use K3bDevice::Device but parses the track offsets + * from the cdda2wav output. + */ +class K3bCdda2wavReader : public K3bJob +{ + Q_OBJECT + + public: + K3bCdda2wavReader( QObject* parent = 0, const char* name = 0 ); + ~K3bCdda2wavReader(); + + bool active() const; + + public slots: + void start(); + void start( bool onlyReadInfo ); + void cancel(); + + void setReadDevice( K3bDevice::Device* dev ) { m_device = dev; } + void setImagePath( const QString& p ) { m_imagePath = p; } + + /** + * the data gets written directly into fd instead of the imagefile. + * Be aware that this only makes sense before starting the job. + * To disable just set fd to -1 + */ + void writeToFd( int fd ); + + private slots: + void slotProcessLine( const QString& ); + void slotProcessExited( KProcess* ); + + private: + K3bDevice::Device* m_device; + + QString m_imagePath; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/jobs/k3bclonejob.cpp b/libk3b/jobs/k3bclonejob.cpp new file mode 100644 index 0000000..9fb61ab --- /dev/null +++ b/libk3b/jobs/k3bclonejob.cpp @@ -0,0 +1,375 @@ +/* + * + * $Id: k3bclonejob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bclonejob.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + + +class K3bCloneJob::Private +{ +public: + Private() + : doneCopies(0) { + } + + int doneCopies; +}; + + +K3bCloneJob::K3bCloneJob( K3bJobHandler* hdl, QObject* parent, const char* name ) + : K3bBurnJob( hdl, parent, name ), + m_writerDevice(0), + m_readerDevice(0), + m_writerJob(0), + m_readcdReader(0), + m_removeImageFiles(false), + m_canceled(false), + m_running(false), + m_simulate(false), + m_speed(1), + m_copies(1), + m_onlyCreateImage(false), + m_onlyBurnExistingImage(false), + m_readRetries(128) +{ + d = new Private; +} + + +K3bCloneJob::~K3bCloneJob() +{ + delete d; +} + + +void K3bCloneJob::start() +{ + jobStarted(); + + m_canceled = false; + m_running = true; + + + // TODO: check the cd size and warn the user if not enough space + + // + // We first check if cdrecord has clone support + // The readcdReader will check the same for readcd + // + const K3bExternalBin* cdrecordBin = k3bcore->externalBinManager()->binObject( "cdrecord" ); + if( !cdrecordBin ) { + emit infoMessage( i18n("Could not find %1 executable.").arg("cdrecord"), ERROR ); + jobFinished(false); + m_running = false; + return; + } + else if( !cdrecordBin->hasFeature( "clone" ) ) { + emit infoMessage( i18n("Cdrecord version %1 does not have cloning support.").arg(cdrecordBin->version), ERROR ); + jobFinished(false); + m_running = false; + return; + } + + if( (!m_onlyCreateImage && !writer()) || + (!m_onlyBurnExistingImage && !readingDevice()) ) { + emit infoMessage( i18n("No device set."), ERROR ); + jobFinished(false); + m_running = false; + return; + } + + if( !m_onlyCreateImage ) { + if( !writer()->supportsWritingMode( K3bDevice::RAW_R96R ) && + !writer()->supportsWritingMode( K3bDevice::RAW_R16 ) ) { + emit infoMessage( i18n("CD writer %1 does not support cloning.") + .arg(writer()->vendor()) + .arg(writer()->description()), ERROR ); + m_running = false; + jobFinished(false); + return; + } + } + + if( m_imagePath.isEmpty() ) { + m_imagePath = K3b::findTempFile( "img" ); + } + else if( QFileInfo(m_imagePath).isDir() ) { + m_imagePath = K3b::findTempFile( "img", m_imagePath ); + } + + if( m_onlyBurnExistingImage ) { + startWriting(); + } + else { + emit burning( false ); + + prepareReader(); + + if( waitForMedia( readingDevice(), + K3bDevice::STATE_COMPLETE, + K3bDevice::MEDIA_WRITABLE_CD|K3bDevice::MEDIA_CD_ROM ) < 0 ) { + m_running = false; + emit canceled(); + jobFinished(false); + return; + } + + emit newTask( i18n("Reading clone image") ); + + m_readcdReader->start(); + } +} + + +void K3bCloneJob::prepareReader() +{ + if( !m_readcdReader ) { + m_readcdReader = new K3bReadcdReader( this, this ); + connect( m_readcdReader, SIGNAL(percent(int)), this, SLOT(slotReadingPercent(int)) ); + connect( m_readcdReader, SIGNAL(percent(int)), this, SIGNAL(subPercent(int)) ); + connect( m_readcdReader, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( m_readcdReader, SIGNAL(finished(bool)), this, SLOT(slotReadingFinished(bool)) ); + connect( m_readcdReader, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_readcdReader, SIGNAL(newTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_readcdReader, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + } + + m_readcdReader->setReadDevice( readingDevice() ); + m_readcdReader->setReadSpeed( 0 ); // MAX + m_readcdReader->setDisableCorrection( m_noCorrection ); + m_readcdReader->setImagePath( m_imagePath ); + m_readcdReader->setClone( true ); + m_readcdReader->setRetries( m_readRetries ); +} + + +void K3bCloneJob::prepareWriter() +{ + if( !m_writerJob ) { + m_writerJob = new K3bCdrecordWriter( writer(), this, this ); + connect( m_writerJob, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_writerJob, SIGNAL(percent(int)), this, SLOT(slotWriterPercent(int)) ); + connect( m_writerJob, SIGNAL(percent(int)), this, SIGNAL(subPercent(int)) ); + connect( m_writerJob, SIGNAL(nextTrack(int, int)), this, SLOT(slotWriterNextTrack(int, int)) ); + connect( m_writerJob, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( m_writerJob, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) ); + connect( m_writerJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); + connect( m_writerJob, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + connect( m_writerJob, SIGNAL(finished(bool)), this, SLOT(slotWriterFinished(bool)) ); + // connect( m_writerJob, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) ); + connect( m_writerJob, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_writerJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + } + + m_writerJob->clearArguments(); + m_writerJob->setWritingMode( K3b::RAW ); + m_writerJob->setClone( true ); + m_writerJob->setSimulate( m_simulate ); + m_writerJob->setBurnSpeed( m_speed ); + m_writerJob->addArgument( m_imagePath ); +} + + +void K3bCloneJob::cancel() +{ + if( m_running ) { + m_canceled = true; + if( m_readcdReader ) + m_readcdReader->cancel(); + if( m_writerJob ) + m_writerJob->cancel(); + } +} + + +void K3bCloneJob::slotWriterPercent( int p ) +{ + if( m_onlyBurnExistingImage ) + emit percent( (int)((double)(d->doneCopies)*100.0/(double)(m_copies) + (double)p/(double)(m_copies)) ); + else + emit percent( (int)((double)(1+d->doneCopies)*100.0/(double)(1+m_copies) + (double)p/(double)(1+m_copies)) ); +} + + +void K3bCloneJob::slotWriterNextTrack( int t, int tt ) +{ + emit newSubTask( i18n("Writing Track %1 of %2").arg(t).arg(tt) ); +} + + +void K3bCloneJob::slotWriterFinished( bool success ) +{ + if( m_canceled ) { + removeImageFiles(); + m_running = false; + emit canceled(); + jobFinished(false); + return; + } + + if( success ) { + d->doneCopies++; + + emit infoMessage( i18n("Successfully written clone copy %1.").arg(d->doneCopies), INFO ); + + if( d->doneCopies < m_copies ) { + K3bDevice::eject( writer() ); + startWriting(); + } + else { + if( m_removeImageFiles ) + removeImageFiles(); + m_running = false; + jobFinished(true); + } + } + else { + removeImageFiles(); + m_running = false; + jobFinished(false); + } +} + + +void K3bCloneJob::slotReadingPercent( int p ) +{ + emit percent( m_onlyCreateImage ? p : (int)((double)p/(double)(1+m_copies)) ); +} + + +void K3bCloneJob::slotReadingFinished( bool success ) +{ + if( m_canceled ) { + removeImageFiles(); + m_running = false; + emit canceled(); + jobFinished(false); + return; + } + + if( success ) { + // + // Make a quick test if the image is really valid. + // Readcd does not seem to have proper exit codes + // + K3bCloneTocReader ctr( m_imagePath ); + if( ctr.isValid() ) { + emit infoMessage( i18n("Successfully read disk."), INFO ); + if( m_onlyCreateImage ) { + m_running = false; + jobFinished(true); + } + else { + if( writer() == readingDevice() ) + K3bDevice::eject( writer() ); + startWriting(); + } + } + else { + emit infoMessage( i18n("Failed to read disk completely in clone mode."), ERROR ); + removeImageFiles(); + m_running = false; + jobFinished(false); + } + } + else { + emit infoMessage( i18n("Error while reading disk."), ERROR ); + removeImageFiles(); + m_running = false; + jobFinished(false); + } +} + + +void K3bCloneJob::startWriting() +{ + emit burning( true ); + + // start writing + prepareWriter(); + + if( waitForMedia( writer(), + K3bDevice::STATE_EMPTY, + K3bDevice::MEDIA_WRITABLE_CD ) < 0 ) { + removeImageFiles(); + m_running = false; + emit canceled(); + jobFinished(false); + return; + } + + if( m_simulate ) + emit newTask( i18n("Simulating clone copy") ); + else + emit newTask( i18n("Writing clone copy %1").arg(d->doneCopies+1) ); + + m_writerJob->start(); +} + + +void K3bCloneJob::removeImageFiles() +{ + if( !m_onlyBurnExistingImage ) { + emit infoMessage( i18n("Removing image files."), INFO ); + if( QFile::exists( m_imagePath ) ) + QFile::remove( m_imagePath ); + if( QFile::exists( m_imagePath + ".toc" ) ) + QFile::remove( m_imagePath + ".toc" ); + } +} + + +QString K3bCloneJob::jobDescription() const +{ + if( m_onlyCreateImage ) + return i18n("Creating Clone Image"); + else if( m_onlyBurnExistingImage ) { + if( m_simulate ) + return i18n("Simulating Clone Image"); + else + return i18n("Burning Clone Image"); + } + else if( m_simulate ) + return i18n("Simulating CD Cloning"); + else + return i18n("Cloning CD"); +} + + +QString K3bCloneJob::jobDetails() const +{ + return i18n("Creating 1 clone copy", + "Creating %n clone copies", + (m_simulate||m_onlyCreateImage) ? 1 : m_copies ); +} + +#include "k3bclonejob.moc" diff --git a/libk3b/jobs/k3bclonejob.h b/libk3b/jobs/k3bclonejob.h new file mode 100644 index 0000000..80c8ea9 --- /dev/null +++ b/libk3b/jobs/k3bclonejob.h @@ -0,0 +1,99 @@ +/* + * + * $Id: k3bclonejob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_CLONE_JOB_H_ +#define _K3B_CLONE_JOB_H_ + +#include +#include "k3b_export.h" +#include + + +namespace K3bDevice { + class Device; +} +class K3bCdrecordWriter; +class K3bReadcdReader; + + +class LIBK3B_EXPORT K3bCloneJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bCloneJob( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bCloneJob(); + + K3bDevice::Device* writer() const { return m_writerDevice; } + K3bDevice::Device* readingDevice() const { return m_readerDevice; } + + QString jobDescription() const; + QString jobDetails() const; + + public slots: + void start(); + void cancel(); + + void setWriterDevice( K3bDevice::Device* w ) { m_writerDevice = w; } + void setReaderDevice( K3bDevice::Device* w ) { m_readerDevice = w; } + void setImagePath( const QString& p ) { m_imagePath = p; } + void setNoCorrection( bool b ) { m_noCorrection = b; } + void setRemoveImageFiles( bool b ) { m_removeImageFiles = b; } + void setOnlyCreateImage( bool b ) { m_onlyCreateImage = b; } + void setOnlyBurnExistingImage( bool b ) { m_onlyBurnExistingImage = b; } + void setSimulate( bool b ) { m_simulate = b; } + void setWriteSpeed( int s ) { m_speed = s; } + void setCopies( int c ) { m_copies = c; } + void setReadRetries( int i ) { m_readRetries = i; } + + private slots: + void slotWriterPercent( int ); + void slotWriterFinished( bool ); + void slotWriterNextTrack( int, int ); + void slotReadingPercent( int ); + void slotReadingFinished( bool ); + + private: + void removeImageFiles(); + void prepareReader(); + void prepareWriter(); + void startWriting(); + + K3bDevice::Device* m_writerDevice; + K3bDevice::Device* m_readerDevice; + QString m_imagePath; + + K3bCdrecordWriter* m_writerJob; + K3bReadcdReader* m_readcdReader; + + bool m_noCorrection; + bool m_removeImageFiles; + + bool m_canceled; + bool m_running; + + bool m_simulate; + int m_speed; + int m_copies; + bool m_onlyCreateImage; + bool m_onlyBurnExistingImage; + int m_readRetries; + + class Private; + Private* d; +}; + + +#endif diff --git a/libk3b/jobs/k3bclonetocreader.cpp b/libk3b/jobs/k3bclonetocreader.cpp new file mode 100644 index 0000000..5dd8b8b --- /dev/null +++ b/libk3b/jobs/k3bclonetocreader.cpp @@ -0,0 +1,235 @@ +/* + * + * $Id: k3bclonetocreader.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include + + +#include "k3bclonetocreader.h" + +#include +#include + +#include +#include + +#include + + +class K3bCloneTocReader::Private +{ +public: + Private() + : size(0) { + } + + K3b::Msf size; + QString tocFile; +}; + + + +K3bCloneTocReader::K3bCloneTocReader( const QString& filename ) + : K3bImageFileReader() +{ + d = new Private; + openFile( filename ); +} + + +K3bCloneTocReader::~K3bCloneTocReader() +{ + delete d; +} + + +const K3b::Msf& K3bCloneTocReader::imageSize() const +{ + return d->size; +} + + +void K3bCloneTocReader::readFile() +{ + // first of all we check if we find the image file which contains the data for this toc + // cdrecord always uses this strange file naming: + // somedata + // somedata.toc + + // filename should always be the toc file + if( filename().right( 4 ) == ".toc" ) + d->tocFile = filename(); + else + d->tocFile = filename() + ".toc"; + + // now get rid of the ".toc" extension + QString imageFileName = d->tocFile.left( d->tocFile.length()-4 ); + if( !QFile::exists( imageFileName ) ) { + kdDebug() << "(K3bCloneTocReader) could not find image file " << imageFileName << endl; + return; + } + + setImageFilename( imageFileName ); + + d->size = 0; + + QFile f( d->tocFile ); + if( f.open( IO_ReadOnly ) ) { + // + // Inspired by clone.c from the cdrecord sources + // + char buffer[2048]; + int read = f.readBlock( buffer, 2048 ); + f.close(); + + if( read == 2048 ) { + kdDebug() << "(K3bCloneTocReader) TOC too large." << endl; + return; + } + + // the toc starts with a tocheader + struct tocheader { + unsigned char len[2]; + unsigned char first; // first session + unsigned char last; // last session + }; + + struct tocheader* th = (struct tocheader*)buffer; + int dataLen = K3bDevice::from2Byte( th->len ) + 2; // the len field does not include it's own length + + if( th->first != 1 ) { + kdDebug() << "(K3bCloneTocReader) first session != 1" << endl; + return; + } + + // the following bytes are multiple instances of + struct ftrackdesc { + unsigned char sess_number; +#ifdef WORDS_BIGENDIAN // __BYTE_ORDER == __BIG_ENDIAN + unsigned char adr : 4; + unsigned char control : 4; +#else + unsigned char control : 4; + unsigned char adr : 4; +#endif + unsigned char track; + unsigned char point; + unsigned char amin; + unsigned char asec; + unsigned char aframe; + unsigned char res7; + unsigned char pmin; + unsigned char psec; + unsigned char pframe; + }; + + for( int i = 4; i < dataLen; i += 11) { + struct ftrackdesc* ft = (struct ftrackdesc*)&buffer[i]; + + if( ft->sess_number != 1 ) { + kdDebug() << "(K3bCloneTocReader} session number != 1" << endl; + return; + } + + // now we check some of the values + if( ft->point >= 0x1 && ft->point <= 0x63 ) { + if( ft->adr == 1 ) { + // check track starttime + if( ft->psec > 60 || ft->pframe > 75 ) { + kdDebug() << "(K3bCloneTocReader) invalid track start: " + << (int)ft->pmin << "." + << (int)ft->psec << "." + << (int)ft->pframe << endl; + return; + } + } + } + else { + switch( ft->point ) { + case 0xa0: + if( ft->adr != 1 ) { + kdDebug() << "(K3bCloneTocReader) adr != 1" << endl; + return; + } + + // disk type in psec + if( ft->psec != 0x00 && ft->psec != 0x10 && ft->psec != 0x20 ) { + kdDebug() << "(K3bCloneTocReader) invalid disktype: " << ft->psec << endl; + return; + } + + if( ft->pmin != 1 ) { + kdDebug() << "(K3bCloneTocReader) first track number != 1 " << endl; + return; + } + + if( ft->pframe != 0x0 ) { + kdDebug() << "(K3bCloneTocReader) found data when there should be 0x0" << endl; + return; + } + break; + + case 0xa1: + if( ft->adr != 1 ) { + kdDebug() << "(K3bCloneTocReader) adr != 1" << endl; + return; + } + + if( !(ft->pmin >= 1) ) { + kdDebug() << "(K3bCloneTocReader) last track number needs to be >= 1." << endl; + return; + } + if( ft->psec != 0x0 || ft->pframe != 0x0 ) { + kdDebug() << "(K3bCloneTocReader) found data when there should be 0x0" << endl; + return; + } + break; + + case 0xa2: + if( ft->adr != 1 ) { + kdDebug() << "(K3bCloneTocReader) adr != 1" << endl; + return; + } + + // start of the leadout = size of the image + // substract 2 seconds since in cdrecord other than in K3b lba 0 = msf 2:00 + // (the cdrecord way is actually more accurate but we use k3b::Msf for many + // things and it is simpler this way.) + d->size = K3b::Msf( ft->pmin, ft->psec, ft->pframe ) - K3b::Msf( 0, 2, 0 ); + + // leadout... no check so far... + break; + + default: + if( ft->adr != 5 ) { + kdDebug() << "(K3bCloneTocReader) adr != 5" << endl; + return; + } + break; + } + } + } + + if( d->size.rawBytes() != K3b::filesize( imageFileName ) ) { + kdDebug() << "(K3bCloneTocReader) image file size invalid." << endl; + return; + } + + // ok, could be a cdrecord toc file + setValid(true); + } + else { + kdDebug() << "(K3bCloneTocReader) could not open file " << d->tocFile << endl; + } +} diff --git a/libk3b/jobs/k3bclonetocreader.h b/libk3b/jobs/k3bclonetocreader.h new file mode 100644 index 0000000..17e80d7 --- /dev/null +++ b/libk3b/jobs/k3bclonetocreader.h @@ -0,0 +1,45 @@ +/* + * + * $Id: k3bclonetocreader.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_CLONETOC_FILE_PARSER_H_ +#define _K3B_CLONETOC_FILE_PARSER_H_ + +#include "k3bimagefilereader.h" + +#include + +#include "k3b_export.h" + + +/** + * Reads a cdrecord clone toc file and searches for the + * corresponding image file. + */ +class LIBK3B_EXPORT K3bCloneTocReader : public K3bImageFileReader +{ + public: + K3bCloneTocReader( const QString& filename = QString::null ); + ~K3bCloneTocReader(); + + const K3b::Msf& imageSize() const; + + protected: + void readFile(); + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/jobs/k3bdatatrackreader.cpp b/libk3b/jobs/k3bdatatrackreader.cpp new file mode 100644 index 0000000..8300ada --- /dev/null +++ b/libk3b/jobs/k3bdatatrackreader.cpp @@ -0,0 +1,515 @@ +/* + * + * $Id: k3bdatatrackreader.cpp 690529 2007-07-21 10:51:47Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bdatatrackreader.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + + + +// FIXME: determine max DMA buffer size +static int s_bufferSizeSectors = 10; + + +class K3bDataTrackReader::WorkThread : public K3bThread +{ +public: + WorkThread(); + ~WorkThread(); + + void init(); + void run(); + int read( unsigned char* buffer, unsigned long sector, unsigned int len ); + bool retryRead( unsigned char* buffer, unsigned long startSector, unsigned int len ); + bool setErrorRecovery( K3bDevice::Device* dev, int code ); + void cancel(); + + bool m_canceled; + bool m_ignoreReadErrors; + bool m_noCorrection; + int m_retries; + K3bDevice::Device* m_device; + K3b::Msf m_firstSector; + K3b::Msf m_lastSector; + K3b::Msf m_nextReadSector; + int m_fd; + QString m_imagePath; + int m_sectorSize; + bool m_useLibdvdcss; + K3bLibDvdCss* m_libcss; + + int m_oldErrorRecoveryMode; + + int m_errorSectorCount; + +private: + int m_usedSectorSize; +}; + + +K3bDataTrackReader::K3bDataTrackReader( K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bThreadJob( jh, parent, name ) +{ + m_thread = new WorkThread(); + setThread( m_thread ); +} + + +K3bDataTrackReader::WorkThread::WorkThread() + : K3bThread(), + m_canceled(false), + m_ignoreReadErrors(false), + m_noCorrection(false), + m_retries(10), + m_device(0), + m_fd(-1), + m_libcss(0) +{ +} + + +K3bDataTrackReader::WorkThread::~WorkThread() +{ + delete m_libcss; +} + + +void K3bDataTrackReader::WorkThread::init() +{ + m_canceled = false; +} + + +void K3bDataTrackReader::WorkThread::run() +{ + emitStarted(); + + if( !m_device->open() ) { + emitInfoMessage( i18n("Could not open device %1").arg(m_device->blockDeviceName()), K3bJob::ERROR ); + emitFinished(false); + return; + } + + // 1. determine sector size by checking the first sectors mode + // if impossible or MODE2 (mode2 formless) finish(false) + + m_useLibdvdcss = false; + m_usedSectorSize = m_sectorSize; + if( m_device->isDVD() ) { + m_usedSectorSize = MODE1; + + // + // In case of an encrypted VideoDVD we read with libdvdcss which takes care of decrypting the vobs + // + if( m_device->copyrightProtectionSystemType() == 1 ) { + + // close the device for libdvdcss + m_device->close(); + + kdDebug() << "(K3bDataTrackReader::WorkThread) found encrypted dvd. using libdvdcss." << endl; + + // open the libdvdcss stuff + if( !m_libcss ) + m_libcss = K3bLibDvdCss::create(); + if( !m_libcss ) { + emitInfoMessage( i18n("Unable to open libdvdcss."), K3bJob::ERROR ); + emitFinished(false); + return; + } + + if( !m_libcss->open(m_device) ) { + emitInfoMessage( i18n("Could not open device %1").arg(m_device->blockDeviceName()), K3bJob::ERROR ); + emitFinished(false); + return; + } + + emitInfoMessage( i18n("Retrieving all CSS keys. This might take a while."), K3bJob::INFO ); + if( !m_libcss->crackAllKeys() ) { + m_libcss->close(); + emitInfoMessage( i18n("Failed to retrieve all CSS keys."), K3bJob::ERROR ); + emitInfoMessage( i18n("Video DVD decryption failed."), K3bJob::ERROR ); + emitFinished(false); + return; + } + + m_useLibdvdcss = true; + } + } + else { + if( m_usedSectorSize == AUTO ) { + switch( m_device->getDataMode( m_firstSector ) ) { + case K3bDevice::Track::MODE1: + case K3bDevice::Track::DVD: + m_usedSectorSize = MODE1; + break; + case K3bDevice::Track::XA_FORM1: + m_usedSectorSize = MODE2FORM1; + break; + case K3bDevice::Track::XA_FORM2: + m_usedSectorSize = MODE2FORM2; + break; + case K3bDevice::Track::MODE2: + emitInfoMessage( i18n("No support for reading formless Mode2 sectors."), K3bJob::ERROR ); + default: + emitInfoMessage( i18n("Unsupported sector type."), K3bJob::ERROR ); + m_device->close(); + emitFinished(false); + return; + } + } + } + + emitInfoMessage( i18n("Reading with sector size %1.").arg(m_usedSectorSize), K3bJob::INFO ); + emitDebuggingOutput( "K3bDataTrackReader", + QString("reading sectors %1 to %2 with sector size %3. Length: %4 sectors, %5 bytes.") + .arg( m_firstSector.lba() ) + .arg( m_lastSector.lba() ) + .arg( m_usedSectorSize ) + .arg( m_lastSector.lba() - m_firstSector.lba() + 1 ) + .arg( Q_UINT64(m_usedSectorSize) * (Q_UINT64)(m_lastSector.lba() - m_firstSector.lba() + 1) ) ); + + QFile file; + if( m_fd == -1 ) { + file.setName( m_imagePath ); + if( !file.open( IO_WriteOnly ) ) { + m_device->close(); + if( m_useLibdvdcss ) + m_libcss->close(); + emitInfoMessage( i18n("Unable to open '%1' for writing.").arg(m_imagePath), K3bJob::ERROR ); + emitFinished( false ); + return; + } + } + + k3bcore->blockDevice( m_device ); + m_device->block( true ); + + // + // set the error recovery mode to 0x21 or 0x20 depending on m_ignoreReadErrors + // TODO: should we also set RC=1 in m_ignoreReadErrors mode (0x11 because TB is ignored) + // + setErrorRecovery( m_device, m_noCorrection ? 0x21 : 0x20 ); + + // + // Let the drive determine the optimal reading speed + // + m_device->setSpeed( 0xffff, 0xffff ); + + s_bufferSizeSectors = 128; + unsigned char* buffer = new unsigned char[m_usedSectorSize*s_bufferSizeSectors]; + while( s_bufferSizeSectors > 0 && read( buffer, m_firstSector.lba(), s_bufferSizeSectors ) < 0 ) { + kdDebug() << "(K3bDataTrackReader) determine max read sectors: " + << s_bufferSizeSectors << " too high." << endl; + s_bufferSizeSectors--; + } + kdDebug() << "(K3bDataTrackReader) determine max read sectors: " + << s_bufferSizeSectors << " is max." << endl; + + // s_bufferSizeSectors = K3bDevice::determineMaxReadingBufferSize( m_device, m_firstSector ); + if( s_bufferSizeSectors <= 0 ) { + emitInfoMessage( i18n("Error while reading sector %1.").arg(m_firstSector.lba()), K3bJob::ERROR ); + emitFinished(false); + m_device->block( false ); + k3bcore->unblockDevice( m_device ); + return; + } + + kdDebug() << "(K3bDataTrackReader) using buffer size of " << s_bufferSizeSectors << " blocks." << endl; + emitDebuggingOutput( "K3bDataTrackReader", QString("using buffer size of %1 blocks.").arg( s_bufferSizeSectors ) ); + + // 2. get it on + K3b::Msf currentSector = m_firstSector; + K3b::Msf totalReadSectors; + m_nextReadSector = 0; + m_errorSectorCount = 0; + bool writeError = false; + bool readError = false; + int lastPercent = 0; + unsigned long lastReadMb = 0; + int bufferLen = s_bufferSizeSectors*m_usedSectorSize; + while( !m_canceled && currentSector <= m_lastSector ) { + + int maxReadSectors = QMIN( bufferLen/m_usedSectorSize, m_lastSector.lba()-currentSector.lba()+1 ); + + int readSectors = read( buffer, + currentSector.lba(), + maxReadSectors ); + if( readSectors < 0 ) { + if( !retryRead( buffer, + currentSector.lba(), + maxReadSectors ) ) { + readError = true; + break; + } + else + readSectors = maxReadSectors; + } + + totalReadSectors += readSectors; + + int readBytes = readSectors * m_usedSectorSize; + + if( m_fd != -1 ) { + if( ::write( m_fd, reinterpret_cast(buffer), readBytes ) != readBytes ) { + kdDebug() << "(K3bDataTrackReader::WorkThread) error while writing to fd " << m_fd + << " current sector: " << (currentSector.lba()-m_firstSector.lba()) << endl; + emitDebuggingOutput( "K3bDataTrackReader", + QString("Error while writing to fd %1. Current sector is %2.") + .arg(m_fd).arg(currentSector.lba()-m_firstSector.lba()) ); + writeError = true; + break; + } + } + else { + if( file.writeBlock( reinterpret_cast(buffer), readBytes ) != readBytes ) { + kdDebug() << "(K3bDataTrackReader::WorkThread) error while writing to file " << m_imagePath + << " current sector: " << (currentSector.lba()-m_firstSector.lba()) << endl; + emitDebuggingOutput( "K3bDataTrackReader", + QString("Error while writing to file %1. Current sector is %2.") + .arg(m_imagePath).arg(currentSector.lba()-m_firstSector.lba()) ); + writeError = true; + break; + } + } + + currentSector += readSectors; + + int percent = 100 * (currentSector.lba() - m_firstSector.lba() + 1 ) / + (m_lastSector.lba() - m_firstSector.lba() + 1 ); + + if( percent > lastPercent ) { + lastPercent = percent; + emitPercent( percent ); + } + + unsigned long readMb = (currentSector.lba() - m_firstSector.lba() + 1) / 512; + if( readMb > lastReadMb ) { + lastReadMb = readMb; + emitProcessedSize( readMb, ( m_lastSector.lba() - m_firstSector.lba() + 1 ) / 512 ); + } + } + + if( m_errorSectorCount > 0 ) + emitInfoMessage( i18n("Ignored %n erroneous sector.", "Ignored a total of %n erroneous sectors.", m_errorSectorCount ), + K3bJob::ERROR ); + + // reset the error recovery mode + setErrorRecovery( m_device, m_oldErrorRecoveryMode ); + + m_device->block( false ); + k3bcore->unblockDevice( m_device ); + + // cleanup + if( m_useLibdvdcss ) + m_libcss->close(); + m_device->close(); + delete [] buffer; + + emitDebuggingOutput( "K3bDataTrackReader", + QString("Read a total of %1 sectors (%2 bytes)") + .arg(totalReadSectors.lba()) + .arg((Q_UINT64)totalReadSectors.lba()*(Q_UINT64)m_usedSectorSize) ); + + if( m_canceled ) + emitCanceled(); + + emitFinished( !m_canceled && !writeError && !readError ); +} + + +int K3bDataTrackReader::WorkThread::read( unsigned char* buffer, unsigned long sector, unsigned int len ) +{ + + // + // Encrypted DVD reading with libdvdcss + // + if( m_useLibdvdcss ) { + return m_libcss->readWrapped( reinterpret_cast(buffer), sector, len ); + } + + // + // Standard reading + // + else { + bool success = false; + // setErrorRecovery( m_device, m_ignoreReadErrors ? 0x21 : 0x20 ); + if( m_usedSectorSize == 2048 ) + success = m_device->read10( buffer, len*2048, sector, len ); + else + success = m_device->readCd( buffer, + len*m_usedSectorSize, + 0, // all sector types + false, // no dap + sector, + len, + false, // no sync + false, // no header + m_usedSectorSize != MODE1, // subheader + true, // user data + false, // no edc/ecc + 0, // no c2 error info... FIXME: should we check this?? + 0 // no subchannel data + ); + + if( success ) + return len; + else + return -1; + } +} + + +// here we read every single sector for itself to find the troubleing ones +bool K3bDataTrackReader::WorkThread::retryRead( unsigned char* buffer, unsigned long startSector, unsigned int len ) +{ + emitDebuggingOutput( "K3bDataTrackReader", QString( "Problem while reading. Retrying from sector %1.").arg(startSector) ); + emitInfoMessage( i18n("Problem while reading. Retrying from sector %1.").arg(startSector), K3bJob::WARNING ); + + int sectorsRead = -1; + bool success = true; + for( unsigned long sector = startSector; sector < startSector+len; ++sector ) { + int retry = m_retries; + while( !m_canceled && retry && (sectorsRead = read( &buffer[( sector - startSector ) * m_usedSectorSize], sector, 1 )) < 0 ) + --retry; + + success = ( sectorsRead > 0 ); + + if( m_canceled ) + return false; + + if( !success ) { + if( m_ignoreReadErrors ) { + emitInfoMessage( i18n("Ignoring read error in sector %1.").arg(sector), K3bJob::ERROR ); + emitDebuggingOutput( "K3bDataTrackReader", QString( "Ignoring read error in sector %1.").arg(sector) ); + + ++m_errorSectorCount; + // ::memset( &buffer[i], 0, 1 ); + success = true; + } + else { + emitInfoMessage( i18n("Error while reading sector %1.").arg(sector), K3bJob::ERROR ); + emitDebuggingOutput( "K3bDataTrackReader", QString( "Read error in sector %1.").arg(sector) ); + break; + } + } + } + + return success; +} + + +bool K3bDataTrackReader::WorkThread::setErrorRecovery( K3bDevice::Device* dev, int code ) +{ + unsigned char* data = 0; + unsigned int dataLen = 0; + if( !dev->modeSense( &data, dataLen, 0x01 ) ) + return false; + + // in MMC1 the page has 8 bytes (12 in MMC4 but we only need the first 3 anyway) + if( dataLen < 8+8 ) { + kdDebug() << "(K3bDataTrackReader) modepage 0x01 data too small: " << dataLen << endl; + delete [] data; + return false; + } + + m_oldErrorRecoveryMode = data[8+2]; + data[8+2] = code; + + if( m_oldErrorRecoveryMode != code ) + kdDebug() << "(K3bDataTrackReader) changing data recovery mode from " << m_oldErrorRecoveryMode << " to " << code << endl; + + bool success = dev->modeSelect( data, dataLen, true, false ); + + delete [] data; + + return success; +} + + +void K3bDataTrackReader::WorkThread::cancel() +{ + m_canceled = true; +} + + + + + +K3bDataTrackReader::~K3bDataTrackReader() +{ + delete m_thread; +} + + +void K3bDataTrackReader::setDevice( K3bDevice::Device* dev ) +{ + m_thread->m_device = dev; +} + + +void K3bDataTrackReader::setSectorRange( const K3b::Msf& start, const K3b::Msf& end ) +{ + m_thread->m_firstSector = start; + m_thread->m_lastSector = end; +} + + +void K3bDataTrackReader::setRetries( int r ) +{ + m_thread->m_retries = r; +} + + +void K3bDataTrackReader::setIgnoreErrors( bool b ) +{ + m_thread->m_ignoreReadErrors = b; +} + + +void K3bDataTrackReader::setNoCorrection( bool b ) +{ + m_thread->m_noCorrection = b; +} + + +void K3bDataTrackReader::writeToFd( int fd ) +{ + m_thread->m_fd = fd; +} + + +void K3bDataTrackReader::setImagePath( const QString& p ) +{ + m_thread->m_imagePath = p; + m_thread->m_fd = -1; +} + + +void K3bDataTrackReader::setSectorSize( SectorSize size ) +{ + m_thread->m_sectorSize = size; +} diff --git a/libk3b/jobs/k3bdatatrackreader.h b/libk3b/jobs/k3bdatatrackreader.h new file mode 100644 index 0000000..814c01c --- /dev/null +++ b/libk3b/jobs/k3bdatatrackreader.h @@ -0,0 +1,87 @@ +/* + * + * $Id: k3bdatatrackreader.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_DATATRACK_READER_H_ +#define _K3B_DATATRACK_READER_H_ + + +#include +#include +#include + +namespace K3bDevice { + class Device; +} + + +/** + * This is a replacement for readcd. We need this since + * it is not possible to influence the sector size used + * by readcd and readcd is not very good to handle anyway. + * + * The sector size read is the following: + * @li Mode1: 2048 bytes (only user data) + * @li Mode2 Form1: 2056 bytes containing the subheader and the user data + * @li Mode2 Form2: 2332 bytes containing the subheader and the user data + * + * Formless Mode2 sectors will not be read. + */ +class K3bDataTrackReader : public K3bThreadJob +{ + public: + K3bDataTrackReader( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bDataTrackReader(); + + enum SectorSize { + AUTO = 0, + MODE1 = K3b::SECTORSIZE_DATA_2048, + MODE2FORM1 = K3b::SECTORSIZE_DATA_2048_SUBHEADER, + MODE2FORM2 = K3b::SECTORSIZE_DATA_2324_SUBHEADER + }; + + void setSectorSize( SectorSize size ); + + void setDevice( K3bDevice::Device* ); + + /** + * @param start the first sector to be read + * @end the last sector to be read + */ + void setSectorRange( const K3b::Msf& start, const K3b::Msf& end ); + void setRetries( int ); + + /** + * If true unreadable sectors will be replaced by zero data to always + * maintain the track length. + */ + void setIgnoreErrors( bool b ); + + void setNoCorrection( bool b ); + + /** + * the data gets written directly into fd instead of the imagefile. + * Be aware that this only makes sense before starting the job. + * To disable just set fd to -1 + */ + void writeToFd( int fd ); + + void setImagePath( const QString& p ); + + private: + class WorkThread; + WorkThread* m_thread; +}; + +#endif diff --git a/libk3b/jobs/k3bdvdcopyjob.cpp b/libk3b/jobs/k3bdvdcopyjob.cpp new file mode 100644 index 0000000..96d727c --- /dev/null +++ b/libk3b/jobs/k3bdvdcopyjob.cpp @@ -0,0 +1,894 @@ +/* + * + * $Id: k3bdvdcopyjob.cpp 690529 2007-07-21 10:51:47Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bdvdcopyjob.h" +#include "k3blibdvdcss.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + + +class K3bDvdCopyJob::Private +{ +public: + Private() + : doneCopies(0), + running(false), + canceled(false), + writerJob(0), + readcdReader(0), + dataTrackReader(0), + verificationJob(0), + usedWritingMode(0), + verifyData(false) { + outPipe.readFromIODevice( &imageFile ); + } + + int doneCopies; + + bool running; + bool readerRunning; + bool writerRunning; + bool canceled; + + K3bGrowisofsWriter* writerJob; + K3bReadcdReader* readcdReader; + K3bDataTrackReader* dataTrackReader; + K3bVerificationJob* verificationJob; + + K3bDevice::DiskInfo sourceDiskInfo; + + K3b::Msf lastSector; + + int usedWritingMode; + + K3bFileSplitter imageFile; + K3bChecksumPipe inPipe; + K3bActivePipe outPipe; + + bool verifyData; +}; + + +K3bDvdCopyJob::K3bDvdCopyJob( K3bJobHandler* hdl, QObject* parent, const char* name ) + : K3bBurnJob( hdl, parent, name ), + m_writerDevice(0), + m_readerDevice(0), + m_onTheFly(false), + m_removeImageFiles(false), + m_simulate(false), + m_speed(1), + m_copies(1), + m_onlyCreateImage(false), + m_ignoreReadErrors(false), + m_readRetries(128), + m_writingMode( K3b::WRITING_MODE_AUTO ) +{ + d = new Private(); +} + + +K3bDvdCopyJob::~K3bDvdCopyJob() +{ + delete d; +} + + +void K3bDvdCopyJob::start() +{ + jobStarted(); + emit burning(false); + + d->canceled = false; + d->running = true; + d->readerRunning = d->writerRunning = false; + + emit newTask( i18n("Checking Source Medium") ); + + if( m_onTheFly && + k3bcore->externalBinManager()->binObject( "growisofs" )->version < K3bVersion( 5, 12 ) ) { + m_onTheFly = false; + emit infoMessage( i18n("K3b does not support writing on-the-fly with growisofs %1.") + .arg(k3bcore->externalBinManager()->binObject( "growisofs" )->version), ERROR ); + emit infoMessage( i18n("Disabling on-the-fly writing."), INFO ); + } + + emit newSubTask( i18n("Waiting for source medium") ); + + // wait for a source disk + if( waitForMedia( m_readerDevice, + K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE, + K3bDevice::MEDIA_WRITABLE_DVD|K3bDevice::MEDIA_DVD_ROM ) < 0 ) { + emit canceled(); + d->running = false; + jobFinished( false ); + return; + } + + emit newSubTask( i18n("Checking source medium") ); + + connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::DISKINFO, m_readerDevice ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotDiskInfoReady(K3bDevice::DeviceHandler*)) ); +} + + +void K3bDvdCopyJob::slotDiskInfoReady( K3bDevice::DeviceHandler* dh ) +{ + if( d->canceled ) { + emit canceled(); + jobFinished(false); + d->running = false; + } + + d->sourceDiskInfo = dh->diskInfo(); + + if( dh->diskInfo().empty() || dh->diskInfo().diskState() == K3bDevice::STATE_NO_MEDIA ) { + emit infoMessage( i18n("No source medium found."), ERROR ); + jobFinished(false); + d->running = false; + } + else { + if( m_readerDevice->copyrightProtectionSystemType() == 1 ) { + emit infoMessage( i18n("Found encrypted DVD."), WARNING ); + // check for libdvdcss + bool haveLibdvdcss = false; + kdDebug() << "(K3bDvdCopyJob) trying to open libdvdcss." << endl; + if( K3bLibDvdCss* libcss = K3bLibDvdCss::create() ) { + kdDebug() << "(K3bDvdCopyJob) succeeded." << endl; + kdDebug() << "(K3bDvdCopyJob) dvdcss_open(" << m_readerDevice->blockDeviceName() << ") = " + << libcss->open(m_readerDevice) << endl; + haveLibdvdcss = true; + + delete libcss; + } + else + kdDebug() << "(K3bDvdCopyJob) failed." << endl; + + if( !haveLibdvdcss ) { + emit infoMessage( i18n("Cannot copy encrypted DVDs."), ERROR ); + d->running = false; + jobFinished( false ); + return; + } + } + + + // + // We cannot rely on the kernel to determine the size of the DVD for some reason + // On the other hand it is not always a good idea to rely on the size from the ISO9660 + // header since that may be wrong due to some buggy encoder or some boot code appended + // after creating the image. + // That is why we try our best to determine the size of the DVD. For DVD-ROM this is very + // easy since it has only one track. The same goes for single session DVD-R(W) and DVD+R. + // Multisession DVDs we will simply not copy. ;) + // For DVD+RW and DVD-RW in restricted overwrite mode we are left with no other choice but + // to use the ISO9660 header. + // + // On the other hand: in on-the-fly mode growisofs determines the size of the data to be written + // by looking at the ISO9660 header when writing in DAO mode. So in this case + // it would be best for us to do the same.... + // + // With growisofs 5.15 we have the option to specify the size of the image to be written in DAO mode. + // + + switch( dh->diskInfo().mediaType() ) { + case K3bDevice::MEDIA_DVD_ROM: + case K3bDevice::MEDIA_DVD_PLUS_R_DL: + case K3bDevice::MEDIA_DVD_R_DL: + case K3bDevice::MEDIA_DVD_R_DL_SEQ: + case K3bDevice::MEDIA_DVD_R_DL_JUMP: + if( !m_onlyCreateImage ) { + if( dh->diskInfo().numLayers() > 1 && + dh->diskInfo().size().mode1Bytes() > 4700372992LL ) { + if( !(m_writerDevice->type() & (K3bDevice::DEVICE_DVD_R_DL|K3bDevice::DEVICE_DVD_PLUS_R_DL)) ) { + emit infoMessage( i18n("The writer does not support writing Double Layer DVD."), ERROR ); + d->running = false; + jobFinished(false); + return; + } + // FIXME: check for growisofs 5.22 (or whatever version is needed) for DVD-R DL + else if( k3bcore->externalBinManager()->binObject( "growisofs" ) && + k3bcore->externalBinManager()->binObject( "growisofs" )->version < K3bVersion( 5, 20 ) ) { + emit infoMessage( i18n("Growisofs >= 5.20 is needed to write Double Layer DVD+R."), ERROR ); + d->running = false; + jobFinished(false); + return; + } + } + } + case K3bDevice::MEDIA_DVD_R: + case K3bDevice::MEDIA_DVD_R_SEQ: + case K3bDevice::MEDIA_DVD_RW: + case K3bDevice::MEDIA_DVD_RW_SEQ: + case K3bDevice::MEDIA_DVD_PLUS_R: + + if( dh->diskInfo().numSessions() > 1 ) { + emit infoMessage( i18n("K3b does not support copying multi-session DVDs."), ERROR ); + d->running = false; + jobFinished(false); + return; + } + + // growisofs only uses the size from the PVD for reserving + // writable space in DAO mode + // with version >= 5.15 growisofs supports specifying the size of the track + if( m_writingMode != K3b::DAO || !m_onTheFly || m_onlyCreateImage || + ( k3bcore->externalBinManager()->binObject( "growisofs" ) && + k3bcore->externalBinManager()->binObject( "growisofs" )->version >= K3bVersion( 5, 15, -1 ) ) ) { + d->lastSector = dh->toc().lastSector(); + break; + } + + // fallthrough + + case K3bDevice::MEDIA_DVD_PLUS_RW: + case K3bDevice::MEDIA_DVD_RW_OVWR: + { + emit infoMessage( i18n("K3b relies on the size saved in the ISO9660 header."), WARNING ); + emit infoMessage( i18n("This might result in a corrupt copy if the source was mastered with buggy software."), WARNING ); + + K3bIso9660 isoF( m_readerDevice, 0 ); + if( isoF.open() ) { + d->lastSector = ((long long)isoF.primaryDescriptor().logicalBlockSize*isoF.primaryDescriptor().volumeSpaceSize)/2048LL - 1; + } + else { + emit infoMessage( i18n("Unable to determine the ISO9660 filesystem size."), ERROR ); + jobFinished(false); + d->running = false; + return; + } + } + break; + + case K3bDevice::MEDIA_DVD_RAM: + emit infoMessage( i18n("K3b does not support copying DVD-RAM."), ERROR ); + jobFinished(false); + d->running = false; + return; + + default: + emit infoMessage( i18n("Unable to determine DVD media type."), ERROR ); + jobFinished(false); + d->running = false; + return; + } + + + if( !m_onTheFly ) { + // + // Check the image path + // + QFileInfo fi( m_imagePath ); + if( !fi.isFile() || + questionYesNo( i18n("Do you want to overwrite %1?").arg(m_imagePath), + i18n("File Exists") ) ) { + if( fi.isDir() ) + m_imagePath = K3b::findTempFile( "iso", m_imagePath ); + else if( !QFileInfo( m_imagePath.section( '/', 0, -2 ) ).isDir() ) { + emit infoMessage( i18n("Specified an unusable temporary path. Using default."), WARNING ); + m_imagePath = K3b::findTempFile( "iso" ); + } + // else the user specified a file in an existing dir + + emit infoMessage( i18n("Writing image file to %1.").arg(m_imagePath), INFO ); + emit newSubTask( i18n("Reading source medium.") ); + } + + // + // check free temp space + // + KIO::filesize_t imageSpaceNeeded = (KIO::filesize_t)(d->lastSector.lba()+1)*2048; + unsigned long avail, size; + QString pathToTest = m_imagePath.left( m_imagePath.findRev( '/' ) ); + if( !K3b::kbFreeOnFs( pathToTest, size, avail ) ) { + emit infoMessage( i18n("Unable to determine free space in temporary directory '%1'.").arg(pathToTest), ERROR ); + jobFinished(false); + d->running = false; + return; + } + else { + if( avail < imageSpaceNeeded/1024 ) { + emit infoMessage( i18n("Not enough space left in temporary directory."), ERROR ); + jobFinished(false); + d->running = false; + return; + } + } + + d->imageFile.setName( m_imagePath ); + if( !d->imageFile.open( IO_WriteOnly ) ) { + emit infoMessage( i18n("Unable to open '%1' for writing.").arg(m_imagePath), ERROR ); + jobFinished( false ); + d->running = false; + return; + } + } + + if( K3b::isMounted( m_readerDevice ) ) { + emit infoMessage( i18n("Unmounting source medium"), INFO ); + K3b::unmount( m_readerDevice ); + } + + if( m_onlyCreateImage || !m_onTheFly ) { + emit newTask( i18n("Creating DVD image") ); + } + else if( m_onTheFly && !m_onlyCreateImage ) { + if( waitForDvd() ) { + prepareWriter(); + if( m_simulate ) + emit newTask( i18n("Simulating DVD copy") ); + else if( m_copies > 1 ) + emit newTask( i18n("Writing DVD copy %1").arg(d->doneCopies+1) ); + else + emit newTask( i18n("Writing DVD copy") ); + + emit burning(true); + d->writerRunning = true; + d->writerJob->start(); + } + else { + if( d->canceled ) + emit canceled(); + jobFinished(false); + d->running = false; + return; + } + } + + prepareReader(); + d->readerRunning = true; + d->dataTrackReader->start(); + } +} + + +void K3bDvdCopyJob::cancel() +{ + if( d->running ) { + d->canceled = true; + if( d->readerRunning ) + d->dataTrackReader->cancel(); + if( d->writerRunning ) + d->writerJob->cancel(); + d->inPipe.close(); + d->outPipe.close(); + d->imageFile.close(); + } + else { + kdDebug() << "(K3bDvdCopyJob) not running." << endl; + } +} + + +void K3bDvdCopyJob::prepareReader() +{ + if( !d->dataTrackReader ) { + d->dataTrackReader = new K3bDataTrackReader( this ); + connect( d->dataTrackReader, SIGNAL(percent(int)), this, SLOT(slotReaderProgress(int)) ); + connect( d->dataTrackReader, SIGNAL(processedSize(int, int)), this, SLOT(slotReaderProcessedSize(int, int)) ); + connect( d->dataTrackReader, SIGNAL(finished(bool)), this, SLOT(slotReaderFinished(bool)) ); + connect( d->dataTrackReader, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( d->dataTrackReader, SIGNAL(newTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( d->dataTrackReader, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + } + + d->dataTrackReader->setDevice( m_readerDevice ); + d->dataTrackReader->setIgnoreErrors( m_ignoreReadErrors ); + d->dataTrackReader->setRetries( m_readRetries ); + d->dataTrackReader->setSectorRange( 0, d->lastSector ); + + if( m_onTheFly && !m_onlyCreateImage ) + d->inPipe.writeToFd( d->writerJob->fd(), true ); + else + d->inPipe.writeToIODevice( &d->imageFile ); + + d->inPipe.open( true ); + d->dataTrackReader->writeToFd( d->inPipe.in() ); +} + + +// ALWAYS CALL WAITFORDVD BEFORE PREPAREWRITER! +void K3bDvdCopyJob::prepareWriter() +{ + delete d->writerJob; + + d->writerJob = new K3bGrowisofsWriter( m_writerDevice, this ); + + connect( d->writerJob, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( d->writerJob, SIGNAL(percent(int)), this, SLOT(slotWriterProgress(int)) ); + connect( d->writerJob, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSize(int, int)) ); + connect( d->writerJob, SIGNAL(processedSubSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( d->writerJob, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) ); + connect( d->writerJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); + connect( d->writerJob, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + connect( d->writerJob, SIGNAL(finished(bool)), this, SLOT(slotWriterFinished(bool)) ); + // connect( d->writerJob, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) ); + connect( d->writerJob, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( d->writerJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + + // these do only make sense with DVD-R(W) + d->writerJob->setSimulate( m_simulate ); + d->writerJob->setBurnSpeed( m_speed ); + d->writerJob->setWritingMode( d->usedWritingMode ); + d->writerJob->setCloseDvd( true ); + + // + // In case the first layer size is not known let the + // split be determined by growisofs + // + if( d->sourceDiskInfo.numLayers() > 1 && + d->sourceDiskInfo.firstLayerSize() > 0 ) { + d->writerJob->setLayerBreak( d->sourceDiskInfo.firstLayerSize().lba() ); + } + else { + // this is only used in DAO mode with growisofs >= 5.15 + d->writerJob->setTrackSize( d->lastSector.lba()+1 ); + } + + d->writerJob->setImageToWrite( QString::null ); // write to stdin +} + + +void K3bDvdCopyJob::slotReaderProgress( int p ) +{ + if( !m_onTheFly || m_onlyCreateImage ) { + emit subPercent( p ); + + int bigParts = ( m_onlyCreateImage ? 1 : (m_simulate ? 2 : ( d->verifyData ? m_copies*2 : m_copies ) + 1 ) ); + emit percent( p/bigParts ); + } +} + + +void K3bDvdCopyJob::slotReaderProcessedSize( int p, int c ) +{ + if( !m_onTheFly || m_onlyCreateImage ) + emit processedSubSize( p, c ); + + if( m_onlyCreateImage ) + emit processedSize( p, c ); +} + + +void K3bDvdCopyJob::slotWriterProgress( int p ) +{ + int bigParts = ( m_simulate ? 1 : ( d->verifyData ? m_copies*2 : m_copies ) ) + ( m_onTheFly ? 0 : 1 ); + int doneParts = ( m_simulate ? 0 : ( d->verifyData ? d->doneCopies*2 : d->doneCopies ) ) + ( m_onTheFly ? 0 : 1 ); + emit percent( 100*doneParts/bigParts + p/bigParts ); + + emit subPercent( p ); +} + + +void K3bDvdCopyJob::slotVerificationProgress( int p ) +{ + int bigParts = ( m_simulate ? 1 : ( d->verifyData ? m_copies*2 : m_copies ) ) + ( m_onTheFly ? 0 : 1 ); + int doneParts = ( m_simulate ? 0 : ( d->verifyData ? d->doneCopies*2 : d->doneCopies ) ) + ( m_onTheFly ? 0 : 1 ) + 1; + emit percent( 100*doneParts/bigParts + p/bigParts ); +} + + +void K3bDvdCopyJob::slotReaderFinished( bool success ) +{ + d->readerRunning = false; + + d->inPipe.close(); + + // close the socket + // otherwise growisofs will never quit. + // FIXME: is it posiible to do this in a generic manner? + if( d->writerJob ) + d->writerJob->closeFd(); + + // already finished? + if( !d->running ) + return; + + if( d->canceled ) { + removeImageFiles(); + emit canceled(); + jobFinished(false); + d->running = false; + } + + if( success ) { + emit infoMessage( i18n("Successfully read source DVD."), SUCCESS ); + if( m_onlyCreateImage ) { + jobFinished(true); + d->running = false; + } + else { + if( m_writerDevice == m_readerDevice ) { + // eject the media (we do this blocking to know if it worked + // because if it did not it might happen that k3b overwrites a CD-RW + // source) + if( !m_readerDevice->eject() ) { + blockingInformation( i18n("K3b was unable to eject the source disk. Please do so manually.") ); + } + } + + if( !m_onTheFly ) { + if( waitForDvd() ) { + prepareWriter(); + if( m_copies > 1 ) + emit newTask( i18n("Writing DVD copy %1").arg(d->doneCopies+1) ); + else + emit newTask( i18n("Writing DVD copy") ); + + emit burning(true); + + d->writerRunning = true; + d->writerJob->start(); + d->outPipe.writeToFd( d->writerJob->fd(), true ); + d->outPipe.open( true ); + } + else { + if( m_removeImageFiles ) + removeImageFiles(); + if( d->canceled ) + emit canceled(); + jobFinished(false); + d->running = false; + } + } + } + } + else { + removeImageFiles(); + jobFinished(false); + d->running = false; + } +} + + +void K3bDvdCopyJob::slotWriterFinished( bool success ) +{ + d->writerRunning = false; + + d->outPipe.close(); + + // already finished? + if( !d->running ) + return; + + if( d->canceled ) { + if( m_removeImageFiles ) + removeImageFiles(); + emit canceled(); + jobFinished(false); + d->running = false; + } + + if( success ) { + emit infoMessage( i18n("Successfully written DVD copy %1.").arg(d->doneCopies+1), INFO ); + + if( d->verifyData && !m_simulate ) { + if( !d->verificationJob ) { + d->verificationJob = new K3bVerificationJob( this, this ); + connect( d->verificationJob, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + connect( d->verificationJob, SIGNAL(newTask(const QString&)), + this, SIGNAL(newSubTask(const QString&)) ); + connect( d->verificationJob, SIGNAL(percent(int)), + this, SLOT(slotVerificationProgress(int)) ); + connect( d->verificationJob, SIGNAL(percent(int)), + this, SIGNAL(subPercent(int)) ); + connect( d->verificationJob, SIGNAL(finished(bool)), + this, SLOT(slotVerificationFinished(bool)) ); + connect( d->verificationJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + + } + d->verificationJob->setDevice( m_writerDevice ); + d->verificationJob->addTrack( 1, d->inPipe.checksum(), d->lastSector+1 ); + + if( m_copies > 1 ) + emit newTask( i18n("Verifying DVD copy %1").arg(d->doneCopies+1) ); + else + emit newTask( i18n("Verifying DVD copy") ); + + emit burning( false ); + + d->verificationJob->start(); + } + + else if( ++d->doneCopies < m_copies ) { + + if ( !m_writerDevice->eject() ) { + blockingInformation( i18n("K3b was unable to eject the written disk. Please do so manually.") ); + } + + if( waitForDvd() ) { + prepareWriter(); + emit newTask( i18n("Writing DVD copy %1").arg(d->doneCopies+1) ); + + emit burning(true); + + d->writerRunning = true; + d->writerJob->start(); + } + else { + if( d->canceled ) + emit canceled(); + jobFinished(false); + d->running = false; + return; + } + + if( m_onTheFly ) { + prepareReader(); + d->readerRunning = true; + d->dataTrackReader->start(); + } + else { + d->outPipe.writeToFd( d->writerJob->fd(), true ); + d->outPipe.open( true ); + } + } + else { + if( m_removeImageFiles ) + removeImageFiles(); + d->running = false; + jobFinished(true); + } + } + else { + if( m_removeImageFiles ) + removeImageFiles(); + d->running = false; + jobFinished(false); + } +} + + +void K3bDvdCopyJob::slotVerificationFinished( bool success ) +{ + // we simply ignore the results from the verification, the verification + // job already emits a message + if( ++d->doneCopies < m_copies ) { + + if( waitForDvd() ) { + prepareWriter(); + emit newTask( i18n("Writing DVD copy %1").arg(d->doneCopies+1) ); + + emit burning(true); + + d->writerRunning = true; + d->writerJob->start(); + } + else { + if( d->canceled ) + emit canceled(); + jobFinished(false); + d->running = false; + return; + } + + if( m_onTheFly ) { + prepareReader(); + d->readerRunning = true; + d->dataTrackReader->start(); + } + else { + d->outPipe.writeToFd( d->writerJob->fd(), true ); + d->outPipe.open( true ); + } + } + else { + if( m_removeImageFiles ) + removeImageFiles(); + d->running = false; + jobFinished( success ); + } +} + + +// this is basically the same code as in K3bDvdJob... :( +// perhaps this should be moved to some K3bGrowisofsHandler which also parses the growisofs output? +bool K3bDvdCopyJob::waitForDvd() +{ + int mt = 0; + if( m_writingMode == K3b::WRITING_MODE_RES_OVWR ) // we treat DVD+R(W) as restricted overwrite media + mt = K3bDevice::MEDIA_DVD_RW_OVWR|K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_PLUS_R; + else + mt = K3bDevice::MEDIA_WRITABLE_DVD_SL; + + // + // in case the source is a double layer DVD we made sure above that the writer + // is capable of writing DVD+R-DL or DVD-R DL and here we wait for a DL DVD + // + if( d->sourceDiskInfo.numLayers() > 1 && + d->sourceDiskInfo.size().mode1Bytes() > 4700372992LL ) { + mt = K3bDevice::MEDIA_WRITABLE_DVD_DL; + } + + int m = waitForMedia( m_writerDevice, K3bDevice::STATE_EMPTY, mt ); + + if( m < 0 ) { + cancel(); + return false; + } + + if( m == 0 ) { + emit infoMessage( i18n("Forced by user. Growisofs will be called without further tests."), INFO ); + } + + else { + // ------------------------------- + // DVD Plus + // ------------------------------- + if( m & K3bDevice::MEDIA_DVD_PLUS_ALL ) { + + d->usedWritingMode = K3b::WRITING_MODE_RES_OVWR; + + if( m_simulate ) { + if( !questionYesNo( i18n("K3b does not support simulation with DVD+R(W) media. " + "Do you really want to continue? The media will actually be " + "written to."), + i18n("No Simulation with DVD+R(W)") ) ) { + cancel(); + return false; + } + +// m_simulate = false; + emit newTask( i18n("Writing DVD copy") ); + } + + if( m_writingMode != K3b::WRITING_MODE_AUTO && m_writingMode != K3b::WRITING_MODE_RES_OVWR ) + emit infoMessage( i18n("Writing mode ignored when writing DVD+R(W) media."), INFO ); + + if( m & K3bDevice::MEDIA_DVD_PLUS_RW ) + emit infoMessage( i18n("Writing DVD+RW."), INFO ); + else if( m & K3bDevice::MEDIA_DVD_PLUS_R_DL ) + emit infoMessage( i18n("Writing Double Layer DVD+R."), INFO ); + else + emit infoMessage( i18n("Writing DVD+R."), INFO ); + } + + // ------------------------------- + // DVD Minus + // ------------------------------- + else { + if( m_simulate && !m_writerDevice->dvdMinusTestwrite() ) { + if( !questionYesNo( i18n("Your writer (%1 %2) does not support simulation with DVD-R(W) media. " + "Do you really want to continue? The media will be written " + "for real.") + .arg(m_writerDevice->vendor()) + .arg(m_writerDevice->description()), + i18n("No Simulation with DVD-R(W)") ) ) { + cancel(); + return false; + } + +// m_simulate = false; + } + + // + // We do not default to DAO in onthefly mode since otherwise growisofs would + // use the size from the PVD to reserve space on the DVD and that can be bad + // if this size is wrong + // With growisofs 5.15 we have the option to specify the size of the image to be written in DAO mode. + // +// bool sizeWithDao = ( k3bcore->externalBinManager()->binObject( "growisofs" ) && +// k3bcore->externalBinManager()->binObject( "growisofs" )->version >= K3bVersion( 5, 15, -1 ) ); + + + // TODO: check for feature 0x21 + + if( m & K3bDevice::MEDIA_DVD_RW_OVWR ) { + emit infoMessage( i18n("Writing DVD-RW in restricted overwrite mode."), INFO ); + d->usedWritingMode = K3b::WRITING_MODE_RES_OVWR; + } + else if( m & (K3bDevice::MEDIA_DVD_RW_SEQ| + K3bDevice::MEDIA_DVD_RW) ) { + if( m_writingMode == K3b::DAO ) { +// ( m_writingMode == K3b::WRITING_MODE_AUTO && +// ( sizeWithDao || !m_onTheFly ) ) ) { + emit infoMessage( i18n("Writing DVD-RW in DAO mode."), INFO ); + d->usedWritingMode = K3b::DAO; + } + else { + emit infoMessage( i18n("Writing DVD-RW in incremental mode."), INFO ); + d->usedWritingMode = K3b::WRITING_MODE_INCR_SEQ; + } + } + else { + + // FIXME: DVD-R DL jump and stuff + + if( m_writingMode == K3b::WRITING_MODE_RES_OVWR ) + emit infoMessage( i18n("Restricted Overwrite is not possible with DVD-R media."), INFO ); + + if( m_writingMode == K3b::DAO ) { +// ( m_writingMode == K3b::WRITING_MODE_AUTO && +// ( sizeWithDao || !m_onTheFly ) ) ) { + emit infoMessage( i18n("Writing %1 in DAO mode.").arg( K3bDevice::mediaTypeString(m, true) ), INFO ); + d->usedWritingMode = K3b::DAO; + } + else { + emit infoMessage( i18n("Writing %1 in incremental mode.").arg( K3bDevice::mediaTypeString(m, true) ), INFO ); + d->usedWritingMode = K3b::WRITING_MODE_INCR_SEQ; + } + } + } + } + + return true; +} + + + +void K3bDvdCopyJob::removeImageFiles() +{ + if( QFile::exists( m_imagePath ) ) { + d->imageFile.remove(); + emit infoMessage( i18n("Removed image file %1").arg(m_imagePath), K3bJob::SUCCESS ); + } +} + + +QString K3bDvdCopyJob::jobDescription() const +{ + if( m_onlyCreateImage ) { + return i18n("Creating DVD Image"); + } + else { + if( m_onTheFly ) + return i18n("Copying DVD On-The-Fly"); + else + return i18n("Copying DVD"); + } +} + + +QString K3bDvdCopyJob::jobDetails() const +{ + return i18n("Creating 1 copy", + "Creating %n copies", + (m_simulate||m_onlyCreateImage) ? 1 : m_copies ); +} + + +void K3bDvdCopyJob::setVerifyData( bool b ) +{ + d->verifyData = b; +} + +#include "k3bdvdcopyjob.moc" diff --git a/libk3b/jobs/k3bdvdcopyjob.h b/libk3b/jobs/k3bdvdcopyjob.h new file mode 100644 index 0000000..91da4e9 --- /dev/null +++ b/libk3b/jobs/k3bdvdcopyjob.h @@ -0,0 +1,99 @@ +/* + * + * $Id: k3bdvdcopyjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_DVD_COPY_JOB_H_ +#define _K3B_DVD_COPY_JOB_H_ + +#include +#include "k3b_export.h" +#include + + +namespace K3bDevice { + class Device; + class DeviceHandler; +} + + +class LIBK3B_EXPORT K3bDvdCopyJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bDvdCopyJob( K3bJobHandler* hdl, QObject* parent = 0, const char* name = 0 ); + ~K3bDvdCopyJob(); + + K3bDevice::Device* writer() const { return m_onlyCreateImage ? 0 : m_writerDevice; } + K3bDevice::Device* readingDevice() const { return m_readerDevice; } + + QString jobDescription() const; + QString jobDetails() const; + + public slots: + void start(); + void cancel(); + + void setWriterDevice( K3bDevice::Device* w ) { m_writerDevice = w; } + void setReaderDevice( K3bDevice::Device* w ) { m_readerDevice = w; } + void setImagePath( const QString& p ) { m_imagePath = p; } + void setRemoveImageFiles( bool b ) { m_removeImageFiles = b; } + void setOnlyCreateImage( bool b ) { m_onlyCreateImage = b; } + void setSimulate( bool b ) { m_simulate = b; } + void setOnTheFly( bool b ) { m_onTheFly = b; } + void setWriteSpeed( int s ) { m_speed = s; } + void setCopies( int c ) { m_copies = c; } + void setWritingMode( int w ) { m_writingMode = w; } + void setIgnoreReadErrors( bool b ) { m_ignoreReadErrors = b; } + void setReadRetries( int i ) { m_readRetries = i; } + void setVerifyData( bool b ); + + private slots: + void slotDiskInfoReady( K3bDevice::DeviceHandler* ); + void slotReaderProgress( int ); + void slotReaderProcessedSize( int, int ); + void slotWriterProgress( int ); + void slotReaderFinished( bool ); + void slotWriterFinished( bool ); + void slotVerificationFinished( bool ); + void slotVerificationProgress( int p ); + + private: + bool waitForDvd(); + void prepareReader(); + void prepareWriter(); + void removeImageFiles(); + + K3bDevice::Device* m_writerDevice; + K3bDevice::Device* m_readerDevice; + QString m_imagePath; + + bool m_onTheFly; + bool m_removeImageFiles; + + bool m_simulate; + int m_speed; + int m_copies; + bool m_onlyCreateImage; + bool m_ignoreReadErrors; + int m_readRetries; + + int m_writingMode; + + class Private; + Private* d; +}; + + +#endif diff --git a/libk3b/jobs/k3bdvdformattingjob.cpp b/libk3b/jobs/k3bdvdformattingjob.cpp new file mode 100644 index 0000000..732e404 --- /dev/null +++ b/libk3b/jobs/k3bdvdformattingjob.cpp @@ -0,0 +1,536 @@ +/* + * + * $Id: k3bdvdformattingjob.cpp 696897 2007-08-06 07:14:14Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bdvdformattingjob.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +class K3bDvdFormattingJob::Private +{ +public: + Private() + : quick(false), + force(false), + mode(K3b::WRITING_MODE_AUTO), + device(0), + process(0), + dvdFormatBin(0), + lastProgressValue(0), + running(false), + forceNoEject(false) { + } + + bool quick; + bool force; + int mode; + + K3bDevice::Device* device; + K3bProcess* process; + const K3bExternalBin* dvdFormatBin; + + int lastProgressValue; + + bool success; + bool canceled; + bool running; + + bool forceNoEject; + + bool error; +}; + + +K3bDvdFormattingJob::K3bDvdFormattingJob( K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bBurnJob( jh, parent, name ) +{ + d = new Private; +} + + +K3bDvdFormattingJob::~K3bDvdFormattingJob() +{ + delete d->process; + delete d; +} + + +K3bDevice::Device* K3bDvdFormattingJob::writer() const +{ + return d->device; +} + + +void K3bDvdFormattingJob::setForceNoEject( bool b ) +{ + d->forceNoEject = b; +} + + +QString K3bDvdFormattingJob::jobDescription() const +{ + return i18n("Formatting DVD"); // Formatting DVD±RW +} + + +QString K3bDvdFormattingJob::jobDetails() const +{ + if( d->quick ) + return i18n("Quick Format"); + else + return QString::null; +} + + +void K3bDvdFormattingJob::start() +{ + d->canceled = false; + d->running = true; + d->error = false; + + jobStarted(); + + if( !d->device ) { + emit infoMessage( i18n("No device set"), ERROR ); + d->running = false; + jobFinished(false); + return; + } + + // FIXME: check the return value + if( K3b::isMounted( d->device ) ) { + emit infoMessage( i18n("Unmounting medium"), INFO ); + K3b::unmount( d->device ); + } + + // + // first wait for a dvd+rw or dvd-rw + // Be aware that an empty DVD-RW might be reformatted to another writing mode + // so we also wait for empty dvds + // + if( waitForMedia( d->device, + K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE|K3bDevice::STATE_EMPTY, + K3bDevice::MEDIA_WRITABLE_DVD, + i18n("Please insert a rewritable DVD medium into drive

%1 %2 (%3).") + .arg(d->device->vendor()).arg(d->device->description()).arg(d->device->devicename()) ) == -1 ) { + emit canceled(); + d->running = false; + jobFinished(false); + return; + } + + emit infoMessage( i18n("Checking media..."), INFO ); + emit newTask( i18n("Checking media") ); + + connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::NG_DISKINFO, d->device ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotDeviceHandlerFinished(K3bDevice::DeviceHandler*)) ); +} + + +void K3bDvdFormattingJob::start( const K3bDevice::DiskInfo& di ) +{ + d->canceled = false; + d->running = true; + + jobStarted(); + + startFormatting( di ); +} + + +void K3bDvdFormattingJob::cancel() +{ + if( d->running ) { + d->canceled = true; + if( d->process ) + d->process->kill(); + } + else { + kdDebug() << "(K3bDvdFormattingJob) not running." << endl; + } +} + + +void K3bDvdFormattingJob::setDevice( K3bDevice::Device* dev ) +{ + d->device = dev; +} + + +void K3bDvdFormattingJob::setMode( int m ) +{ + d->mode = m; +} + + +void K3bDvdFormattingJob::setQuickFormat( bool b ) +{ + d->quick = b; +} + + +void K3bDvdFormattingJob::setForce( bool b ) +{ + d->force = b; +} + + +void K3bDvdFormattingJob::slotStderrLine( const QString& line ) +{ +// * DVD±RW format utility by , version 4.4. +// * 4.7GB DVD-RW media in Sequential mode detected. +// * blanking 100.0| + +// * formatting 100.0| + + emit debuggingOutput( "dvd+rw-format", line ); + + // parsing for the -gui mode (since dvd+rw-format 4.6) + int pos = line.find( "blanking" ); + if( pos < 0 ) + pos = line.find( "formatting" ); + if( pos >= 0 ) { + pos = line.find( QRegExp( "\\d" ), pos ); + } + // parsing for \b\b... stuff + else if( !line.startsWith("*") ) { + pos = line.find( QRegExp( "\\d" ) ); + } + else if( line.startsWith( ":-(" ) ) { + if( line.startsWith( ":-( unable to proceed with format" ) ) { + d->error = true; + } + } + + if( pos >= 0 ) { + int endPos = line.find( QRegExp("[^\\d\\.]"), pos ) - 1; + bool ok; + int progress = (int)(line.mid( pos, endPos - pos ).toDouble(&ok)); + if( ok ) { + d->lastProgressValue = progress; + emit percent( progress ); + } + else { + kdDebug() << "(K3bDvdFormattingJob) parsing error: '" << line.mid( pos, endPos - pos ) << "'" << endl; + } + } +} + + +void K3bDvdFormattingJob::slotProcessFinished( KProcess* p ) +{ + if( d->canceled ) { + emit canceled(); + d->success = false; + } + else if( p->normalExit() ) { + if( !d->error && p->exitStatus() == 0 ) { + emit infoMessage( i18n("Formatting successfully completed"), K3bJob::SUCCESS ); + + if( d->lastProgressValue < 100 ) { + emit infoMessage( i18n("Do not be concerned with the progress stopping before 100%."), INFO ); + emit infoMessage( i18n("The formatting will continue in the background while writing."), INFO ); + } + + d->success = true; + } + else { + emit infoMessage( i18n("%1 returned an unknown error (code %2).").arg(d->dvdFormatBin->name()).arg(p->exitStatus()), + K3bJob::ERROR ); + emit infoMessage( i18n("Please send me an email with the last output."), K3bJob::ERROR ); + + d->success = false; + } + } + else { + emit infoMessage( i18n("%1 did not exit cleanly.").arg(d->dvdFormatBin->name()), + ERROR ); + d->success = false; + } + + if( d->forceNoEject || + !k3bcore->globalSettings()->ejectMedia() ) { + d->running = false; + jobFinished(d->success); + } + else { + emit infoMessage( i18n("Ejecting DVD..."), INFO ); + connect( K3bDevice::eject( d->device ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotEjectingFinished(K3bDevice::DeviceHandler*)) ); + } +} + + +void K3bDvdFormattingJob::slotEjectingFinished( K3bDevice::DeviceHandler* dh ) +{ + if( !dh->success() ) + emit infoMessage( i18n("Unable to eject media."), ERROR ); + + d->running = false; + jobFinished(d->success); +} + + +void K3bDvdFormattingJob::slotDeviceHandlerFinished( K3bDevice::DeviceHandler* dh ) +{ + if( d->canceled ) { + emit canceled(); + jobFinished(false); + d->running = false; + } + + if( dh->success() ) { + startFormatting( dh->diskInfo() ); + } + else { + emit infoMessage( i18n("Unable to determine media state."), ERROR ); + d->running = false; + jobFinished(false); + } +} + + +void K3bDvdFormattingJob::startFormatting( const K3bDevice::DiskInfo& diskInfo ) +{ + // + // Now check the media type: + // if DVD-RW: use d->mode + // emit warning if formatting is full and stuff + // + // in overwrite mode: emit info that progress might stop before 100% since formatting will continue + // in the background once the media gets rewritten (only DVD+RW?) + // + + // emit info about what kind of media has been found + + if( !(diskInfo.mediaType() & (K3bDevice::MEDIA_DVD_RW| + K3bDevice::MEDIA_DVD_RW_SEQ| + K3bDevice::MEDIA_DVD_RW_OVWR| + K3bDevice::MEDIA_DVD_PLUS_RW)) ) { + emit infoMessage( i18n("No rewritable DVD media found. Unable to format."), ERROR ); + d->running = false; + jobFinished(false); + return; + } + + + bool format = true; // do we need to format + bool blank = false; // blank is for DVD-RW sequential incremental + // DVD-RW restricted overwrite and DVD+RW uses the force option (or no option at all) + + + + // + // DVD+RW is quite easy to handle. There is only one possible mode and it is always recommended to not + // format it more than once but to overwrite it once it is formatted + // Once the initial formatting has been done it's always "appendable" (or "complete"???) + // + + + if( diskInfo.mediaType() == K3bDevice::MEDIA_DVD_PLUS_RW ) { + emit infoMessage( i18n("Found %1 media.").arg(K3bDevice::mediaTypeString(K3bDevice::MEDIA_DVD_PLUS_RW)), + INFO ); + + // mode is ignored + + if( diskInfo.empty() ) { + // + // The DVD+RW is blank and needs to be initially formatted + // + blank = false; + } + else { + emit infoMessage( i18n("No need to format %1 media more than once.") + .arg(K3bDevice::mediaTypeString(K3bDevice::MEDIA_DVD_PLUS_RW)), INFO ); + emit infoMessage( i18n("It may simply be overwritten."), INFO ); + + if( d->force ) { + emit infoMessage( i18n("Forcing formatting anyway."), INFO ); + emit infoMessage( i18n("It is not recommended to force formatting of DVD+RW media."), INFO ); + emit infoMessage( i18n("Already after 10-20 reformats the media might be unusable."), INFO ); + blank = false; + } + else { + format = false; + } + } + + if( format ) + emit newSubTask( i18n("Formatting DVD+RW") ); + } + + + + // + // DVD-RW has two modes: incremental sequential (the default which is also needed for DAO writing) + // and restricted overwrite which compares to the DVD+RW mode. + // + + else { // MEDIA_DVD_RW + emit infoMessage( i18n("Found %1 media.").arg(K3bDevice::mediaTypeString(K3bDevice::MEDIA_DVD_RW)), + INFO ); + + if( diskInfo.currentProfile() != K3bDevice::MEDIA_UNKNOWN ) { + emit infoMessage( i18n("Formatted in %1 mode.").arg(K3bDevice::mediaTypeString(diskInfo.currentProfile())), INFO ); + + + // + // Is it possible to have an empty DVD-RW in restricted overwrite mode???? I don't think so. + // + + if( diskInfo.empty() && + (d->mode == K3b::WRITING_MODE_AUTO || + (d->mode == K3b::WRITING_MODE_INCR_SEQ && + diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_SEQ) || + (d->mode == K3b::WRITING_MODE_RES_OVWR && + diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_OVWR) ) + ) { + emit infoMessage( i18n("Media is already empty."), INFO ); + if( d->force ) + emit infoMessage( i18n("Forcing formatting anyway."), INFO ); + else + format = false; + } + else if( diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_OVWR && + d->mode != K3b::WRITING_MODE_INCR_SEQ ) { + emit infoMessage( i18n("No need to format %1 media more than once.") + .arg(K3bDevice::mediaTypeString(diskInfo.currentProfile())), INFO ); + emit infoMessage( i18n("It may simply be overwritten."), INFO ); + + if( d->force ) + emit infoMessage( i18n("Forcing formatting anyway."), INFO ); + else + format = false; + } + + + if( format ) { + if( d->mode == K3b::WRITING_MODE_AUTO ) { + // just format in the same mode as the media is currently formatted + blank = (diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_SEQ); + } + else { + blank = (d->mode == K3b::WRITING_MODE_INCR_SEQ); + } + + emit newSubTask( i18n("Formatting" + " DVD-RW in %1 mode.").arg(K3bDevice::mediaTypeString( blank ? + K3bDevice::MEDIA_DVD_RW_SEQ : + K3bDevice::MEDIA_DVD_RW_OVWR )) ); + } + } + else { + emit infoMessage( i18n("Unable to determine the current formatting state of the DVD-RW media."), ERROR ); + d->running = false; + jobFinished(false); + return; + } + } + + + if( format ) { + delete d->process; + d->process = new K3bProcess(); + d->process->setRunPrivileged(true); + // d->process->setSuppressEmptyLines(false); + connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotStderrLine(const QString&)) ); + connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessFinished(KProcess*)) ); + + d->dvdFormatBin = k3bcore->externalBinManager()->binObject( "dvd+rw-format" ); + if( !d->dvdFormatBin ) { + emit infoMessage( i18n("Could not find %1 executable.").arg("dvd+rw-format"), ERROR ); + d->running = false; + jobFinished(false); + return; + } + + if( !d->dvdFormatBin->copyright.isEmpty() ) + emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3").arg(d->dvdFormatBin->name()).arg(d->dvdFormatBin->version).arg(d->dvdFormatBin->copyright), INFO ); + + + *d->process << d->dvdFormatBin; + + if( d->dvdFormatBin->version >= K3bVersion( 4, 6 ) ) + *d->process << "-gui"; + + QString p; + if( blank ) + p = "-blank"; + else + p = "-force"; + if( !d->quick ) + p += "=full"; + + *d->process << p; + + *d->process << d->device->blockDeviceName(); + + // additional user parameters from config + const QStringList& params = d->dvdFormatBin->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *d->process << *it; + + kdDebug() << "***** dvd+rw-format parameters:\n"; + const QValueList& args = d->process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << endl << flush; + emit debuggingOutput( "dvd+rw-format command:", s ); + + if( !d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) { + // something went wrong when starting the program + // it "should" be the executable + kdDebug() << "(K3bDvdFormattingJob) could not start " << d->dvdFormatBin->path << endl; + emit infoMessage( i18n("Could not start %1.").arg(d->dvdFormatBin->name()), K3bJob::ERROR ); + d->running = false; + jobFinished(false); + } + else { + emit newTask( i18n("Formatting") ); + } + } + else { + // already formatted :) + d->running = false; + jobFinished(true); + } +} + + +#include "k3bdvdformattingjob.moc" diff --git a/libk3b/jobs/k3bdvdformattingjob.h b/libk3b/jobs/k3bdvdformattingjob.h new file mode 100644 index 0000000..10672cb --- /dev/null +++ b/libk3b/jobs/k3bdvdformattingjob.h @@ -0,0 +1,91 @@ +/* + * + * $Id: k3bdvdformattingjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_DVD_FORMATTING_JOB_H_ +#define _K3B_DVD_FORMATTING_JOB_H_ + + +#include +#include "k3b_export.h" + +class KProcess; +namespace K3bDevice { + class Device; + class DeviceHandler; +} + + +class LIBK3B_EXPORT K3bDvdFormattingJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bDvdFormattingJob( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bDvdFormattingJob(); + + QString jobDescription() const; + QString jobDetails() const; + + K3bDevice::Device* writer() const; + + public slots: + void start(); + + /** + * Use this to force the start of the formatting without checking for a usable medium. + */ + void start( const K3bDevice::DiskInfo& ); + + void cancel(); + + void setDevice( K3bDevice::Device* ); + + /** + * One of: WRITING_MODE_INCR_SEQ, WRITING_MODE_RES_OVWR + * Ignored for DVD+RW + */ + void setMode( int ); + + /** + * Not all writers support this + */ + void setQuickFormat( bool ); + + /** + * @param b If true empty DVDs will also be formatted + */ + void setForce( bool b ); + + /** + * If set true the job ignores the global K3b setting + * and does not eject the CD-RW after finishing + */ + void setForceNoEject( bool ); + + private slots: + void slotStderrLine( const QString& ); + void slotProcessFinished( KProcess* ); + void slotDeviceHandlerFinished( K3bDevice::DeviceHandler* ); + void slotEjectingFinished( K3bDevice::DeviceHandler* ); + + private: + void startFormatting( const K3bDevice::DiskInfo& ); + + class Private; + Private* d; +}; + + +#endif diff --git a/libk3b/jobs/k3biso9660imagewritingjob.cpp b/libk3b/jobs/k3biso9660imagewritingjob.cpp new file mode 100644 index 0000000..1fb3871 --- /dev/null +++ b/libk3b/jobs/k3biso9660imagewritingjob.cpp @@ -0,0 +1,458 @@ +/* + * + * $Id: k3biso9660imagewritingjob.cpp 690187 2007-07-20 09:18:03Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3biso9660imagewritingjob.h" +#include "k3bverificationjob.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +class K3bIso9660ImageWritingJob::Private +{ +public: + K3bChecksumPipe checksumPipe; + K3bFileSplitter imageFile; +}; + + +K3bIso9660ImageWritingJob::K3bIso9660ImageWritingJob( K3bJobHandler* hdl ) + : K3bBurnJob( hdl ), + m_writingMode(K3b::WRITING_MODE_AUTO), + m_simulate(false), + m_device(0), + m_noFix(false), + m_speed(2), + m_dataMode(K3b::DATA_MODE_AUTO), + m_writer(0), + m_tocFile(0), + m_copies(1), + m_verifyJob(0) +{ + d = new Private; +} + +K3bIso9660ImageWritingJob::~K3bIso9660ImageWritingJob() +{ + delete m_tocFile; + delete d; +} + + +void K3bIso9660ImageWritingJob::start() +{ + m_canceled = m_finished = false; + m_currentCopy = 1; + + jobStarted(); + + if( m_simulate ) + m_verifyData = false; + + emit newTask( i18n("Preparing data") ); + + if( !QFile::exists( m_imagePath ) ) { + emit infoMessage( i18n("Could not find image %1").arg(m_imagePath), K3bJob::ERROR ); + jobFinished( false ); + return; + } + + unsigned long gb = K3b::imageFilesize( m_imagePath )/1024/1024; + + // very rough test but since most dvd images are 4,x or 8,x GB it should be enough + m_dvd = ( gb > 900 ); + + startWriting(); +} + + +void K3bIso9660ImageWritingJob::slotWriterJobFinished( bool success ) +{ + if( m_canceled ) { + m_finished = true; + emit canceled(); + jobFinished(false); + return; + } + + d->checksumPipe.close(); + + if( success ) { + if( !m_simulate && m_verifyData ) { + emit burning(false); + + // allright + // the writerJob should have emited the "simulation/writing successful" signal + + if( !m_verifyJob ) { + m_verifyJob = new K3bVerificationJob( this ); + connectSubJob( m_verifyJob, + SLOT(slotVerificationFinished(bool)), + true, + SLOT(slotVerificationProgress(int)), + SIGNAL(subPercent(int)) ); + } + m_verifyJob->setDevice( m_device ); + m_verifyJob->clear(); + m_verifyJob->addTrack( 1, d->checksumPipe.checksum(), K3b::imageFilesize( m_imagePath )/2048 ); + + if( m_copies == 1 ) + emit newTask( i18n("Verifying written data") ); + else + emit newTask( i18n("Verifying written copy %1 of %2").arg(m_currentCopy).arg(m_copies) ); + + m_verifyJob->start(); + } + else if( m_currentCopy >= m_copies ) { + m_finished = true; + jobFinished(true); + } + else { + m_currentCopy++; + startWriting(); + } + } + else { + m_finished = true; + jobFinished(false); + } +} + + +void K3bIso9660ImageWritingJob::slotVerificationFinished( bool success ) +{ + if( m_canceled ) { + m_finished = true; + emit canceled(); + jobFinished(false); + return; + } + + if( success && m_currentCopy < m_copies ) { + m_currentCopy++; + connect( K3bDevice::eject( m_device ), SIGNAL(finished(bool)), + this, SLOT(startWriting()) ); + return; + } + + k3bcore->config()->setGroup("General Options"); + if( !k3bcore->config()->readBoolEntry( "No cd eject", false ) ) + K3bDevice::eject( m_device ); + + m_finished = true; + jobFinished( success ); +} + + +void K3bIso9660ImageWritingJob::slotVerificationProgress( int p ) +{ + emit percent( (int)(100.0 / (double)m_copies * ( (double)(m_currentCopy-1) + 0.5 + (double)p/200.0 )) ); +} + + +void K3bIso9660ImageWritingJob::slotWriterPercent( int p ) +{ + emit subPercent( p ); + + if( m_verifyData ) + emit percent( (int)(100.0 / (double)m_copies * ( (double)(m_currentCopy-1) + ((double)p/200.0) )) ); + else + emit percent( (int)(100.0 / (double)m_copies * ( (double)(m_currentCopy-1) + ((double)p/100.0) )) ); +} + + +void K3bIso9660ImageWritingJob::slotNextTrack( int, int ) +{ + if( m_copies == 1 ) + emit newSubTask( i18n("Writing image") ); + else + emit newSubTask( i18n("Writing copy %1 of %2").arg(m_currentCopy).arg(m_copies) ); +} + + +void K3bIso9660ImageWritingJob::cancel() +{ + if( !m_finished ) { + m_canceled = true; + + if( m_writer ) + m_writer->cancel(); + if( m_verifyData && m_verifyJob ) + m_verifyJob->cancel(); + } +} + + +void K3bIso9660ImageWritingJob::startWriting() +{ + emit newSubTask( i18n("Waiting for medium") ); + + // we wait for the following: + // 1. if writing mode auto and writing app auto: all writable media types + // 2. if writing mode auto and writing app not growisofs: all writable cd types + // 3. if writing mode auto and writing app growisofs: all writable dvd types + // 4. if writing mode TAO or RAW: all writable cd types + // 5. if writing mode DAO and writing app auto: all writable cd types and DVD-R(W) + // 6. if writing mode DAO and writing app GROWISOFS: DVD-R(W) + // 7. if writing mode DAO and writing app CDRDAO or CDRECORD: all writable cd types + // 8. if writing mode WRITING_MODE_INCR_SEQ: DVD-R(W) + // 9. if writing mode WRITING_MODE_RES_OVWR: DVD-RW or DVD+RW + + int mt = 0; + if( m_writingMode == K3b::WRITING_MODE_AUTO ) { + if( writingApp() == K3b::DEFAULT ) { + if( m_dvd ) + mt = K3bDevice::MEDIA_WRITABLE_DVD; + else + mt = K3bDevice::MEDIA_WRITABLE_CD; + } + else if( writingApp() != K3b::GROWISOFS ) + mt = K3bDevice::MEDIA_WRITABLE_CD; + else + mt = K3bDevice::MEDIA_WRITABLE_DVD; + } + else if( m_writingMode == K3b::TAO || m_writingMode == K3b::RAW ) + mt = K3bDevice::MEDIA_WRITABLE_CD; + else if( m_writingMode == K3b::DAO ) { + if( writingApp() == K3b::DEFAULT ) { + if( m_dvd ) + mt = K3bDevice::MEDIA_WRITABLE_DVD; + else + mt = K3bDevice::MEDIA_WRITABLE_CD; + } + else if( writingApp() == K3b::GROWISOFS ) + mt = K3bDevice::MEDIA_WRITABLE_DVD; + else + mt = K3bDevice::MEDIA_WRITABLE_CD; + } + else if( m_writingMode == K3b::WRITING_MODE_RES_OVWR ) + mt = K3bDevice::MEDIA_DVD_PLUS_R|K3bDevice::MEDIA_DVD_PLUS_R_DL|K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_RW_OVWR; + else + mt = K3bDevice::MEDIA_WRITABLE_DVD; + + + // wait for the media + int media = waitForMedia( m_device, K3bDevice::STATE_EMPTY, mt ); + if( media < 0 ) { + m_finished = true; + emit canceled(); + jobFinished(false); + return; + } + + // we simply always calculate the checksum, thus making the code simpler + d->imageFile.close(); + d->imageFile.setName( m_imagePath ); + d->imageFile.open( IO_ReadOnly ); + d->checksumPipe.close(); + d->checksumPipe.readFromIODevice( &d->imageFile ); + + if( prepareWriter( media ) ) { + emit burning(true); + m_writer->start(); + d->checksumPipe.writeToFd( m_writer->fd(), true ); + d->checksumPipe.open( K3bChecksumPipe::MD5, true ); + } + else { + m_finished = true; + jobFinished(false); + } +} + + +bool K3bIso9660ImageWritingJob::prepareWriter( int mediaType ) +{ + if( mediaType == 0 ) { // media forced + // just to get it going... + if( writingApp() != K3b::GROWISOFS && !m_dvd ) + mediaType = K3bDevice::MEDIA_CD_R; + else + mediaType = K3bDevice::MEDIA_DVD_R; + } + + delete m_writer; + + if( mediaType == K3bDevice::MEDIA_CD_R || mediaType == K3bDevice::MEDIA_CD_RW ) { + int usedWritingMode = m_writingMode; + if( usedWritingMode == K3b::WRITING_MODE_AUTO ) { + // cdrecord seems to have problems when writing in mode2 in dao mode + // so with cdrecord we use TAO + if( m_noFix || m_dataMode == K3b::MODE2 || !m_device->dao() ) + usedWritingMode = K3b::TAO; + else + usedWritingMode = K3b::DAO; + } + + int usedApp = writingApp(); + if( usedApp == K3b::DEFAULT ) { + if( usedWritingMode == K3b::DAO && + ( m_dataMode == K3b::MODE2 || m_noFix ) ) + usedApp = K3b::CDRDAO; + else + usedApp = K3b::CDRECORD; + } + + + if( usedApp == K3b::CDRECORD ) { + K3bCdrecordWriter* writer = new K3bCdrecordWriter( m_device, this ); + + writer->setWritingMode( usedWritingMode ); + writer->setSimulate( m_simulate ); + writer->setBurnSpeed( m_speed ); + + if( m_noFix ) { + writer->addArgument("-multi"); + } + + if( (m_dataMode == K3b::DATA_MODE_AUTO && m_noFix) || + m_dataMode == K3b::MODE2 ) { + if( k3bcore->externalBinManager()->binObject("cdrecord") && + k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "xamix" ) ) + writer->addArgument( "-xa" ); + else + writer->addArgument( "-xa1" ); + } + else + writer->addArgument("-data"); + + // read from stdin + writer->addArgument( QString("-tsize=%1s").arg( K3b::imageFilesize( m_imagePath )/2048 ) )->addArgument( "-" ); + + m_writer = writer; + } + else { + // create cdrdao job + K3bCdrdaoWriter* writer = new K3bCdrdaoWriter( m_device, this ); + writer->setCommand( K3bCdrdaoWriter::WRITE ); + writer->setSimulate( m_simulate ); + writer->setBurnSpeed( m_speed ); + // multisession + writer->setMulti( m_noFix ); + + // now write the tocfile + delete m_tocFile; + m_tocFile = new KTempFile( QString::null, "toc" ); + m_tocFile->setAutoDelete(true); + + if( QTextStream* s = m_tocFile->textStream() ) { + if( (m_dataMode == K3b::DATA_MODE_AUTO && m_noFix) || + m_dataMode == K3b::MODE2 ) { + *s << "CD_ROM_XA" << "\n"; + *s << "\n"; + *s << "TRACK MODE2_FORM1" << "\n"; + } + else { + *s << "CD_ROM" << "\n"; + *s << "\n"; + *s << "TRACK MODE1" << "\n"; + } + *s << "DATAFILE \"-\" " << QString::number( K3b::imageFilesize( m_imagePath ) ) << "\n"; + + m_tocFile->close(); + } + else { + kdDebug() << "(K3bDataJob) could not write tocfile." << endl; + emit infoMessage( i18n("IO Error"), ERROR ); + return false; + } + + writer->setTocFile( m_tocFile->name() ); + + m_writer = writer; + } + } + else { // DVD + if( mediaType & K3bDevice::MEDIA_DVD_PLUS_ALL ) { + if( m_simulate ) { + if( questionYesNo( i18n("K3b does not support simulation with DVD+R(W) media. " + "Do you really want to continue? The media will be written " + "for real."), + i18n("No Simulation with DVD+R(W)") ) ) { + return false; + } + } + + m_simulate = false; + } + + K3bGrowisofsWriter* writer = new K3bGrowisofsWriter( m_device, this ); + writer->setSimulate( m_simulate ); + writer->setBurnSpeed( m_speed ); + writer->setWritingMode( m_writingMode == K3b::DAO ? K3b::DAO : 0 ); + writer->setImageToWrite( QString::null ); // read from stdin + writer->setCloseDvd( !m_noFix ); + writer->setTrackSize( K3b::imageFilesize( m_imagePath )/2048 ); + + m_writer = writer; + } + + connect( m_writer, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_writer, SIGNAL(nextTrack(int, int)), this, SLOT(slotNextTrack(int, int)) ); + connect( m_writer, SIGNAL(percent(int)), this, SLOT(slotWriterPercent(int)) ); + connect( m_writer, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSize(int, int)) ); + connect( m_writer, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) ); + connect( m_writer, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); + connect( m_writer, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + connect( m_writer, SIGNAL(finished(bool)), this, SLOT(slotWriterJobFinished(bool)) ); + connect( m_writer, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) ); + connect( m_writer, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_writer, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + + return true; +} + + +QString K3bIso9660ImageWritingJob::jobDescription() const +{ + if( m_simulate ) + return i18n("Simulating ISO9660 Image"); + else + return ( i18n("Burning ISO9660 Image") + + ( m_copies > 1 + ? i18n(" - %n Copy", " - %n Copies", m_copies) + : QString::null ) ); +} + + +QString K3bIso9660ImageWritingJob::jobDetails() const +{ + return m_imagePath.section("/", -1) + QString( " (%1)" ).arg(KIO::convertSize(K3b::filesize(KURL::fromPathOrURL(m_imagePath)))); +} + + +#include "k3biso9660imagewritingjob.moc" diff --git a/libk3b/jobs/k3biso9660imagewritingjob.h b/libk3b/jobs/k3biso9660imagewritingjob.h new file mode 100644 index 0000000..eceb6dc --- /dev/null +++ b/libk3b/jobs/k3biso9660imagewritingjob.h @@ -0,0 +1,98 @@ +/* + * + * $Id$ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BISO9660_IMAGE_WRITING_JOB_H +#define K3BISO9660_IMAGE_WRITING_JOB_H + +#include +#include "k3b_export.h" +class QString; +class K3bAbstractWriter; +class KTempFile; +namespace K3bDevice { + class Device; +} +class K3bVerificationJob; + + +/** + *@author Sebastian Trueg + */ +class LIBK3B_EXPORT K3bIso9660ImageWritingJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bIso9660ImageWritingJob( K3bJobHandler* ); + ~K3bIso9660ImageWritingJob(); + + K3bDevice::Device* writer() const { return m_device; }; + + QString jobDescription() const; + QString jobDetails() const; + + public slots: + void cancel(); + void start(); + + void setImagePath( const QString& path ) { m_imagePath = path; } + void setSpeed( int s ) { m_speed = s; } + void setBurnDevice( K3bDevice::Device* dev ) { m_device = dev; } + void setWritingMode( int mode ) { m_writingMode = mode; } + void setSimulate( bool b ) { m_simulate = b; } + void setNoFix( bool b ) { m_noFix = b; } + void setDataMode( int m ) { m_dataMode = m; } + void setVerifyData( bool b ) { m_verifyData = b; } + void setCopies( int c ) { m_copies = c; } + + protected slots: + void slotWriterJobFinished( bool ); + void slotVerificationFinished( bool ); + void slotVerificationProgress( int ); + void slotWriterPercent( int ); + void slotNextTrack( int, int ); + void startWriting(); + + private: + bool prepareWriter( int mediaType ); + + int m_writingMode; + bool m_simulate; + K3bDevice::Device* m_device; + bool m_noFix; + int m_speed; + int m_dataMode; + bool m_verifyData; + bool m_dvd; + + QString m_imagePath; + + K3bAbstractWriter* m_writer; + KTempFile* m_tocFile; + + bool m_canceled; + bool m_finished; + + int m_copies; + int m_currentCopy; + + K3bVerificationJob* m_verifyJob; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/jobs/k3breadcdreader.cpp b/libk3b/jobs/k3breadcdreader.cpp new file mode 100644 index 0000000..d75eb63 --- /dev/null +++ b/libk3b/jobs/k3breadcdreader.cpp @@ -0,0 +1,335 @@ +/* + * + * $Id: k3breadcdreader.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3breadcdreader.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + + + +class K3bReadcdReader::Private +{ +public: + Private() + : process(0), + fdToWriteTo(-1), + canceled(false) { + } + + K3b::Msf firstSector, lastSector; + + K3bProcess* process; + const K3bExternalBin* readcdBinObject; + + int fdToWriteTo; + bool canceled; + + long blocksToRead; + int unreadableBlocks; + + int lastProgress; + int lastProcessedSize; +}; + + + +K3bReadcdReader::K3bReadcdReader( K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bJob( jh, parent, name ), + m_noCorr(false), + m_clone(false), + m_noError(false), + m_c2Scan(false), + m_speed(0), + m_retries(128) +{ + d = new Private(); +} + + +K3bReadcdReader::~K3bReadcdReader() +{ + delete d->process; + delete d; +} + + +bool K3bReadcdReader::active() const +{ + return (d->process ? d->process->isRunning() : false); +} + + +void K3bReadcdReader::writeToFd( int fd ) +{ + d->fdToWriteTo = fd; +} + + +void K3bReadcdReader::start() +{ + jobStarted(); + + d->blocksToRead = 1; + d->unreadableBlocks = 0; + d->lastProgress = 0; + d->lastProcessedSize = 0; + + // the first thing to do is to check for readcd + d->readcdBinObject = k3bcore->externalBinManager()->binObject( "readcd" ); + if( !d->readcdBinObject ) { + emit infoMessage( i18n("Could not find %1 executable.").arg("readcd"), ERROR ); + jobFinished(false); + return; + } + + // check if we have clone support if we need it + if( m_clone ) { + bool foundCloneSupport = false; + + if( !d->readcdBinObject->hasFeature( "clone" ) ) { + // search all readcd installations + K3bExternalProgram* readcdProgram = k3bcore->externalBinManager()->program( "readcd" ); + const QPtrList& readcdBins = readcdProgram->bins(); + for( QPtrListIterator it( readcdBins ); it.current(); ++it ) { + if( it.current()->hasFeature( "clone" ) ) { + d->readcdBinObject = it.current(); + emit infoMessage( i18n("Using readcd %1 instead of default version for clone support.").arg(d->readcdBinObject->version), INFO ); + foundCloneSupport = true; + break; + } + } + + if( !foundCloneSupport ) { + emit infoMessage( i18n("Could not find readcd executable with cloning support."), ERROR ); + jobFinished(false); + return; + } + } + } + + + // create the commandline + delete d->process; + d->process = new K3bProcess(); + connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotStdLine(const QString&)) ); + connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited(KProcess*)) ); + + + *d->process << d->readcdBinObject; + + // display progress + *d->process << "-v"; + + // Again we assume the device to be set! + *d->process << QString("dev=%1").arg(K3b::externalBinDeviceParameter(m_readDevice, + d->readcdBinObject)); + if( m_speed > 0 ) + *d->process << QString("speed=%1").arg(m_speed); + + + // output + if( d->fdToWriteTo != -1 ) { + *d->process << "f=-"; + d->process->dupStdout( d->fdToWriteTo ); + } + else { + emit newTask( i18n("Writing image to %1.").arg(m_imagePath) ); + emit infoMessage( i18n("Writing image to %1.").arg(m_imagePath), INFO ); + *d->process << "f=" + m_imagePath; + } + + + if( m_noError ) + *d->process << "-noerror"; + if( m_clone ) { + *d->process << "-clone"; + // noCorr can only be used with cloning + if( m_noCorr ) + *d->process << "-nocorr"; + } + if( m_c2Scan ) + *d->process << "-c2scan"; + + *d->process << QString("retries=%1").arg(m_retries); + + // readcd does not read the last sector specified + if( d->firstSector < d->lastSector ) + *d->process << QString("sectors=%1-%2").arg(d->firstSector.lba()).arg(d->lastSector.lba()+1); + + // Joerg sais it is a Linux kernel bug, anyway, with the default value it does not work + *d->process << "ts=128k"; + + // additional user parameters from config + const QStringList& params = d->readcdBinObject->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *d->process << *it; + + + kdDebug() << "***** readcd parameters:\n"; + const QValueList& args = d->process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << endl << flush; + + emit debuggingOutput("readcd command:", s); + + d->canceled = false; + + if( !d->process->start( KProcess::NotifyOnExit, KProcess::AllOutput) ) { + // something went wrong when starting the program + // it "should" be the executable + kdError() << "(K3bReadcdReader) could not start readcd" << endl; + emit infoMessage( i18n("Could not start readcd."), K3bJob::ERROR ); + jobFinished( false ); + } +} + + +void K3bReadcdReader::cancel() +{ + if( d->process ) { + if( d->process->isRunning() ) { + d->canceled = true; + d->process->kill(); + } + } +} + + +void K3bReadcdReader::slotStdLine( const QString& line ) +{ + emit debuggingOutput( "readcd", line ); + + int pos = -1; + + if( line.startsWith( "end:" ) ) { + bool ok; + d->blocksToRead = line.mid(4).toInt(&ok); + if( d->firstSector < d->lastSector ) + d->blocksToRead -= d->firstSector.lba(); + if( !ok ) + kdError() << "(K3bReadcdReader) blocksToRead parsing error in line: " + << line.mid(4) << endl; + } + + else if( line.startsWith( "addr:" ) ) { + bool ok; + long currentReadBlock = line.mid( 6, line.find("cnt")-7 ).toInt(&ok); + if( d->firstSector < d->lastSector ) + currentReadBlock -= d->firstSector.lba(); + if( ok ) { + int p = (int)(100.0 * (double)currentReadBlock / (double)d->blocksToRead); + if( p > d->lastProgress ) { + emit percent( p ); + d->lastProgress = p; + } + int ps = currentReadBlock*2/1024; + if( ps > d->lastProcessedSize ) { + emit processedSize( ps, d->blocksToRead*2/1024 ); + d->lastProcessedSize = ps; + } + } + else + kdError() << "(K3bReadcdReader) currentReadBlock parsing error in line: " + << line.mid( 6, line.find("cnt")-7 ) << endl; + } + + else if( line.contains("Cannot read source disk") ) { + emit infoMessage( i18n("Cannot read source disk."), ERROR ); + } + + else if( (pos = line.find("Retrying from sector")) >= 0 ) { + // parse the sector + pos += 21; + bool ok; + int problemSector = line.mid( pos, line.find( QRegExp("\\D"), pos )-pos ).toInt(&ok); + if( !ok ) { + kdError() << "(K3bReadcdReader) problemSector parsing error in line: " + << line.mid( pos, line.find( QRegExp("\\D"), pos )-pos ) << endl; + } + emit infoMessage( i18n("Retrying from sector %1.").arg(problemSector), INFO ); + } + + else if( (pos = line.find("Error on sector")) >= 0 ) { + d->unreadableBlocks++; + + pos += 16; + bool ok; + int problemSector = line.mid( pos, line.find( QRegExp("\\D"), pos )-pos ).toInt(&ok); + if( !ok ) { + kdError() << "(K3bReadcdReader) problemSector parsing error in line: " + << line.mid( pos, line.find( QRegExp("\\D"), pos )-pos ) << endl; + } + + if( line.contains( "not corrected") ) { + emit infoMessage( i18n("Uncorrected error in sector %1").arg(problemSector), ERROR ); + } + else { + emit infoMessage( i18n("Corrected error in sector %1").arg(problemSector), ERROR ); + } + } + + else { + kdDebug() << "(readcd) " << line << endl; + } +} + +void K3bReadcdReader::slotProcessExited( KProcess* p ) +{ + if( d->canceled ) { + emit canceled(); + jobFinished(false); + } + else if( p->normalExit() ) { + if( p->exitStatus() == 0 ) { + jobFinished( true ); + } + else { + emit infoMessage( i18n("%1 returned error: %2").arg("Readcd").arg(p->exitStatus()), ERROR ); + jobFinished( false ); + } + } + else { + emit infoMessage( i18n("Readcd exited abnormally."), ERROR ); + jobFinished( false ); + } +} + + +void K3bReadcdReader::setSectorRange( const K3b::Msf& first, const K3b::Msf& last ) +{ + d->firstSector = first; + d->lastSector = last; +} + +#include "k3breadcdreader.moc" + diff --git a/libk3b/jobs/k3breadcdreader.h b/libk3b/jobs/k3breadcdreader.h new file mode 100644 index 0000000..93ebce0 --- /dev/null +++ b/libk3b/jobs/k3breadcdreader.h @@ -0,0 +1,91 @@ +/* + * + * $Id: k3breadcdreader.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_READCD_READER_H_ +#define _K3B_READCD_READER_H_ + +#include + + +class K3bProcess; +class KProcess; +class K3bExternalBin; +namespace K3bDevice { + class Device; +} +namespace K3b { + class Msf; +} + + +class K3bReadcdReader : public K3bJob +{ + Q_OBJECT + + public: + K3bReadcdReader( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bReadcdReader(); + + bool active() const; + + public slots: + void start(); + void cancel(); + + void setReadDevice( K3bDevice::Device* dev ) { m_readDevice = dev; } + + /** 0 means MAX */ + void setReadSpeed( int s ) { m_speed = s; } + void setDisableCorrection( bool b ) { m_noCorr = b; } + + /** default: true */ + void setAbortOnError( bool b ) { m_noError = !b; } + void setC2Scan( bool b ) { m_c2Scan = b; } + void setClone( bool b ) { m_clone = b; } + void setRetries( int i ) { m_retries = i; } + + void setSectorRange( const K3b::Msf&, const K3b::Msf& ); + + void setImagePath( const QString& p ) { m_imagePath = p; } + + /** + * the data gets written directly into fd instead of the imagefile. + * Be aware that this only makes sense before starting the job. + * To disable just set fd to -1 + */ + void writeToFd( int fd ); + + private slots: + void slotStdLine( const QString& line ); + void slotProcessExited(KProcess*); + + private: + bool m_noCorr; + bool m_clone; + bool m_noError; + bool m_c2Scan; + int m_speed; + int m_retries; + + K3bDevice::Device* m_readDevice; + + QString m_imagePath; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/jobs/k3bverificationjob.cpp b/libk3b/jobs/k3bverificationjob.cpp new file mode 100644 index 0000000..e73530e --- /dev/null +++ b/libk3b/jobs/k3bverificationjob.cpp @@ -0,0 +1,384 @@ +/* + * + * $Id: k3bisoimageverificationjob.cpp 597651 2006-10-21 08:04:01Z trueg $ + * Copyright (C) 2003-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bverificationjob.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +class K3bVerificationJobTrackEntry +{ +public: + K3bVerificationJobTrackEntry() + : trackNumber(0) { + } + + K3bVerificationJobTrackEntry( int tn, const QCString& cs, const K3b::Msf& msf ) + : trackNumber(tn), + checksum(cs), + length(msf) { + } + + int trackNumber; + QCString checksum; + K3b::Msf length; +}; + + +class K3bVerificationJob::Private +{ +public: + Private() + : md5Job(0), + device(0), + dataTrackReader(0) { + } + + bool canceled; + K3bMd5Job* md5Job; + K3bDevice::Device* device; + + K3b::Msf grownSessionSize; + + QValueList tracks; + int currentTrackIndex; + + K3bDevice::DiskInfo diskInfo; + K3bDevice::Toc toc; + + K3bDataTrackReader* dataTrackReader; + + K3b::Msf currentTrackSize; + K3b::Msf totalSectors; + K3b::Msf alreadyReadSectors; + + K3bPipe pipe; + + bool readSuccessful; + + bool mediumHasBeenReloaded; +}; + + +K3bVerificationJob::K3bVerificationJob( K3bJobHandler* hdl, QObject* parent, const char* name ) + : K3bJob( hdl, parent, name ) +{ + d = new Private(); + + d->md5Job = new K3bMd5Job( this ); + connect( d->md5Job, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( d->md5Job, SIGNAL(finished(bool)), this, SLOT(slotMd5JobFinished(bool)) ); + connect( d->md5Job, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); +} + + +K3bVerificationJob::~K3bVerificationJob() +{ + delete d; +} + + +void K3bVerificationJob::cancel() +{ + d->canceled = true; + if( d->md5Job && d->md5Job->active() ) + d->md5Job->cancel(); + if( d->dataTrackReader && d->dataTrackReader->active() ) + d->dataTrackReader->cancel(); +} + + +void K3bVerificationJob::addTrack( int trackNum, const QCString& checksum, const K3b::Msf& length ) +{ + d->tracks.append( K3bVerificationJobTrackEntry( trackNum, checksum, length ) ); +} + + +void K3bVerificationJob::clear() +{ + d->tracks.clear(); + d->grownSessionSize = 0; +} + + +void K3bVerificationJob::setDevice( K3bDevice::Device* dev ) +{ + d->device = dev; +} + + +void K3bVerificationJob::setGrownSessionSize( const K3b::Msf& s ) +{ + d->grownSessionSize = s; +} + + +void K3bVerificationJob::start() +{ + jobStarted(); + + d->canceled = false; + d->currentTrackIndex = 0; + d->alreadyReadSectors = 0; + + emit newTask( i18n("Checking medium") ); + + d->mediumHasBeenReloaded = false; + connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::DISKINFO, d->device ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotDiskInfoReady(K3bDevice::DeviceHandler*)) ); +} + + +void K3bVerificationJob::slotMediaReloaded( bool /*success*/ ) +{ + // we always need to wait for the medium. Otherwise the diskinfo below + // may run before the drive is ready! + waitForMedia( d->device, + K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE, + K3bDevice::MEDIA_WRITABLE ); + + d->mediumHasBeenReloaded = true; + + emit newTask( i18n("Checking medium") ); + + connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::DISKINFO, d->device ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotDiskInfoReady(K3bDevice::DeviceHandler*)) ); +} + + +void K3bVerificationJob::slotDiskInfoReady( K3bDevice::DeviceHandler* dh ) +{ + if( d->canceled ) { + emit canceled(); + jobFinished(false); + } + + d->diskInfo = dh->diskInfo(); + d->toc = dh->toc(); + d->totalSectors = 0; + + // just to be sure check if we actually have all the tracks + int i = 0; + for( QValueList::iterator it = d->tracks.begin(); + it != d->tracks.end(); ++i, ++it ) { + + // 0 means "last track" + if( (*it).trackNumber == 0 ) + (*it).trackNumber = d->toc.count(); + + if( (int)d->toc.count() < (*it).trackNumber ) { + if ( d->mediumHasBeenReloaded ) { + emit infoMessage( i18n("Internal Error: Verification job improperly initialized (%1)") + .arg( "Specified track number not found on medium" ), ERROR ); + jobFinished( false ); + return; + } + else { + // many drives need to reload the medium to return to a proper state + emit newTask( i18n("Reloading the medium") ); + connect( K3bDevice::reload( d->device ), + SIGNAL(finished(bool)), + this, + SLOT(slotMediaReloaded(bool)) ); + return; + } + } + + d->totalSectors += trackLength( i ); + } + + readTrack( 0 ); +} + + +void K3bVerificationJob::readTrack( int trackIndex ) +{ + d->currentTrackIndex = trackIndex; + d->readSuccessful = true; + + d->currentTrackSize = trackLength( trackIndex ); + if( d->currentTrackSize == 0 ) { + jobFinished(false); + return; + } + + emit newTask( i18n("Verifying track %1").arg( d->tracks[trackIndex].trackNumber ) ); + + d->pipe.open(); + + if( d->toc[d->tracks[trackIndex].trackNumber-1].type() == K3bDevice::Track::DATA ) { + if( !d->dataTrackReader ) { + d->dataTrackReader = new K3bDataTrackReader( this ); + connect( d->dataTrackReader, SIGNAL(percent(int)), this, SLOT(slotReaderProgress(int)) ); + // connect( d->dataTrackReader, SIGNAL(processedSize(int, int)), this, SLOT(slotReaderProcessedSize(int, int)) ); + connect( d->dataTrackReader, SIGNAL(finished(bool)), this, SLOT(slotReaderFinished(bool)) ); + connect( d->dataTrackReader, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( d->dataTrackReader, SIGNAL(newTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( d->dataTrackReader, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + } + + d->dataTrackReader->setDevice( d->device ); + d->dataTrackReader->setIgnoreErrors( false ); + d->dataTrackReader->setSectorSize( K3bDataTrackReader::MODE1 ); + + // in case a session was grown the track size does not say anything about the verification data size + if( d->diskInfo.mediaType() & (K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_RW_OVWR) && + d->grownSessionSize > 0 ) { + K3bIso9660 isoF( d->device ); + if( isoF.open() ) { + int firstSector = isoF.primaryDescriptor().volumeSpaceSize - d->grownSessionSize.lba(); + d->dataTrackReader->setSectorRange( firstSector, + isoF.primaryDescriptor().volumeSpaceSize -1 ); + } + else { + emit infoMessage( i18n("Unable to determine the ISO9660 filesystem size."), ERROR ); + jobFinished( false ); + return; + } + } + else + d->dataTrackReader->setSectorRange( d->toc[d->tracks[trackIndex].trackNumber-1].firstSector(), + d->toc[d->tracks[trackIndex].trackNumber-1].firstSector() + d->currentTrackSize -1 ); + + d->md5Job->setMaxReadSize( d->currentTrackSize.mode1Bytes() ); + + d->dataTrackReader->writeToFd( d->pipe.in() ); + d->dataTrackReader->start(); + } + else { + // FIXME: handle audio tracks + } + + d->md5Job->setFd( d->pipe.out() ); + d->md5Job->start(); +} + + +void K3bVerificationJob::slotReaderProgress( int p ) +{ + emit subPercent( p ); + + emit percent( 100 * ( d->alreadyReadSectors.lba() + ( p*d->currentTrackSize.lba()/100 ) ) / d->totalSectors.lba() ); +} + + +void K3bVerificationJob::slotMd5JobFinished( bool success ) +{ + d->pipe.close(); + + if( success && !d->canceled && d->readSuccessful ) { + // compare the two sums + if( d->tracks[d->currentTrackIndex].checksum != d->md5Job->hexDigest() ) { + emit infoMessage( i18n("Written data in track %1 differs from original.").arg(d->tracks[d->currentTrackIndex].trackNumber), ERROR ); + jobFinished(false); + } + else { + emit infoMessage( i18n("Written data verified."), SUCCESS ); + ++d->currentTrackIndex; + if( d->currentTrackIndex < (int)d->tracks.count() ) + readTrack( d->currentTrackIndex ); + else + jobFinished(true); + } + } + else { + // The md5job emitted an error message. So there is no need to do this again + jobFinished(false); + } +} + + +void K3bVerificationJob::slotReaderFinished( bool success ) +{ + d->readSuccessful = success; + if( !d->readSuccessful ) + d->md5Job->cancel(); + else { + d->alreadyReadSectors += trackLength( d->currentTrackIndex ); + + // close the pipe and let the md5 job finish gracefully + d->pipe.closeIn(); + // d->md5Job->stop(); + } +} + + +K3b::Msf K3bVerificationJob::trackLength( int trackIndex ) +{ + K3b::Msf& trackSize = d->tracks[trackIndex].length; + const int& trackNum = d->tracks[trackIndex].trackNumber; + + if( trackSize == 0 ) { + trackSize = d->toc[trackNum-1].length(); + + if( d->diskInfo.mediaType() & (K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_RW_OVWR) ) { + K3bIso9660 isoF( d->device, d->toc[trackNum-1].firstSector().lba() ); + if( isoF.open() ) { + trackSize = isoF.primaryDescriptor().volumeSpaceSize; + } + else { + emit infoMessage( i18n("Unable to determine the ISO9660 filesystem size."), ERROR ); + return 0; + } + } + + // + // A data track recorded in TAO mode has two run-out blocks which cannot be read and contain + // zero data anyway. The problem is that I do not know of a valid method to determine if a track + // was written in TAO (the control nibble does definitely not work, I never saw one which did not + // equal 4). + // So the solution for now is to simply try to read the last sector of a data track. If this is not + // possible we assume it was written in TAO mode and reduce the length by 2 sectors + // + if( d->toc[trackNum-1].type() == K3bDevice::Track::DATA && + d->diskInfo.mediaType() & K3bDevice::MEDIA_CD_ALL ) { + // we try twice just to be sure + unsigned char buffer[2048]; + if( !d->device->read10( buffer, 2048, d->toc[trackNum-1].lastSector().lba(), 1 ) && + !d->device->read10( buffer, 2048, d->toc[trackNum-1].lastSector().lba(), 1 ) ) { + trackSize -= 2; + kdDebug() << "(K3bCdCopyJob) track " << trackNum << " probably TAO recorded." << endl; + } + } + } + + return trackSize; +} + + +#include "k3bverificationjob.moc" diff --git a/libk3b/jobs/k3bverificationjob.h b/libk3b/jobs/k3bverificationjob.h new file mode 100644 index 0000000..ad750ee --- /dev/null +++ b/libk3b/jobs/k3bverificationjob.h @@ -0,0 +1,92 @@ +/* + * + * $Id: k3bisoimageverificationjob.h 597651 2006-10-21 08:04:01Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VERIFICATION_JOB_H_ +#define _K3B_VERIFICATION_JOB_H_ + +#include + +namespace K3bDevice { + class Device; + class DeviceHandler; +} + + +/** + * Generic verification job. Add tracks to be verified via addTrack. + * The job will then verifiy the tracks set against the set checksums. + * + * The different track types are handled as follows: + * \li Data/DVD tracks: Read the track with a 2048 bytes sector size. + * Tracks length on DVD+RW media will be read from the iso9660 + * descriptor. + * \li Audio tracks: Rip the track with a 2352 bytes sector size. + * In the case of audio tracks the job will not fail if the checksums + * differ becasue audio CD tracks do not contain error correction data. + * In this case only a warning will be emitted. + * + * Other sector sizes than 2048 bytes for data tracks are not supported yet, + * i.e. Video CDs cannot be verified. + * + * TAO written tracks have two run-out sectors that are not read. + * + * The VerificationJob will also reload the medium before starting. + */ +class K3bVerificationJob : public K3bJob +{ + Q_OBJECT + + public: + K3bVerificationJob( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bVerificationJob(); + + public slots: + void start(); + void cancel(); + void setDevice( K3bDevice::Device* dev ); + + void clear(); + + /** + * Add a track to be verified. + * \param tracknum The number of the track. If \a tracknum is 0 + * the last track will be verified. + * \param length Set to override the track length from the TOC. This may be + * useful when writing to DVD+RW media and the iso descriptor does not + * contain the exact image size (as true for many commercial Video DVDs) + */ + void addTrack( int tracknum, const QCString& checksum, const K3b::Msf& length = K3b::Msf() ); + + /** + * Handle the special case of iso session growing + */ + void setGrownSessionSize( const K3b::Msf& ); + + private slots: + void slotMediaReloaded( bool success ); + void slotDiskInfoReady( K3bDevice::DeviceHandler* dh ); + void readTrack( int trackIndex ); + void slotMd5JobFinished( bool success ); + void slotReaderProgress( int p ); + void slotReaderFinished( bool success ); + + private: + K3b::Msf trackLength( int trackNum ); + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/jobs/k3bvideodvdtitledetectclippingjob.cpp b/libk3b/jobs/k3bvideodvdtitledetectclippingjob.cpp new file mode 100644 index 0000000..fdcc3a4 --- /dev/null +++ b/libk3b/jobs/k3bvideodvdtitledetectclippingjob.cpp @@ -0,0 +1,291 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bvideodvdtitledetectclippingjob.h" + +#include +#include +#include +#include + +#include +#include + + +static const int s_unrealisticHighClippingValue = 100000; + + +class K3bVideoDVDTitleDetectClippingJob::Private +{ +public: + const K3bExternalBin* usedTranscodeBin; + + K3bProcess* process; + + bool canceled; + + unsigned int currentChapter; + unsigned int currentFrames; + unsigned int totalChapters; + + int lastProgress; + int lastSubProgress; +}; + + + +K3bVideoDVDTitleDetectClippingJob::K3bVideoDVDTitleDetectClippingJob( K3bJobHandler* hdl, QObject* parent ) + : K3bJob( hdl, parent ), + m_clippingTop( 0 ), + m_clippingBottom( 0 ), + m_clippingLeft( 0 ), + m_clippingRight( 0 ), + m_lowPriority( true ) +{ + d = new Private; + d->process = 0; +} + + +K3bVideoDVDTitleDetectClippingJob::~K3bVideoDVDTitleDetectClippingJob() +{ + delete d->process; + delete d; +} + + +void K3bVideoDVDTitleDetectClippingJob::start() +{ + jobStarted(); + + d->canceled = false; + d->lastProgress = 0; + + // + // It seems as if the last chapter is often way too short + // + d->totalChapters = m_dvd[m_titleNumber-1].numPTTs(); + if( d->totalChapters > 1 && m_dvd[m_titleNumber-1][d->totalChapters-1].playbackTime().totalFrames() < 200 ) + d->totalChapters--; + + // initial values (some way to big value) + m_clippingTop = s_unrealisticHighClippingValue; + m_clippingBottom = s_unrealisticHighClippingValue; + m_clippingLeft = s_unrealisticHighClippingValue; + m_clippingRight = s_unrealisticHighClippingValue; + + d->usedTranscodeBin = k3bcore->externalBinManager()->binObject("transcode"); + if( !d->usedTranscodeBin ) { + emit infoMessage( i18n("%1 executable could not be found.").arg("transcode"), ERROR ); + jobFinished( false ); + return; + } + + if( d->usedTranscodeBin->version < K3bVersion( 1, 0, 0 ) ){ + emit infoMessage( i18n("%1 version %2 is too old.") + .arg("transcode") + .arg(d->usedTranscodeBin->version), ERROR ); + jobFinished( false ); + return; + } + + emit debuggingOutput( "Used versions", "transcode: " + d->usedTranscodeBin->version ); + + if( !d->usedTranscodeBin->copyright.isEmpty() ) + emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3") + .arg(d->usedTranscodeBin->name()) + .arg(d->usedTranscodeBin->version) + .arg(d->usedTranscodeBin->copyright), INFO ); + + emit newTask( i18n("Analysing Title %1 of Video DVD %2").arg(m_titleNumber).arg(m_dvd.volumeIdentifier()) ); + + startTranscode( 1 ); +} + + +void K3bVideoDVDTitleDetectClippingJob::startTranscode( int chapter ) +{ + d->currentChapter = chapter; + d->lastSubProgress = 0; + + // + // If we have only one chapter and it is not longer than 2 minutes (value guessed based on some test DVD) + // use the whole chapter + // + if( d->totalChapters == 1 ) + d->currentFrames = QMIN( 3000, QMAX( 1, m_dvd[m_titleNumber-1][d->currentChapter-1].playbackTime().totalFrames() ) ); + else + d->currentFrames = QMIN( 200, QMAX( 1, m_dvd[m_titleNumber-1][d->currentChapter-1].playbackTime().totalFrames() ) ); + + // + // prepare the process + // + delete d->process; + d->process = new K3bProcess(); + d->process->setSuppressEmptyLines(true); + d->process->setSplitStdout(true); + // connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotTranscodeStderr(const QString&)) ); + connect( d->process, SIGNAL(stdoutLine(const QString&)), this, SLOT(slotTranscodeStderr(const QString&)) ); + connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotTranscodeExited(KProcess*)) ); + + // the executable + *d->process << d->usedTranscodeBin; + + // low priority + if( m_lowPriority ) + *d->process << "--nice" << "19"; + + // the input + *d->process << "-i" << m_dvd.device()->blockDeviceName(); + + // select the title number and chapter + *d->process << "-T" << QString("%1,%2").arg(m_titleNumber).arg(chapter); + + // null output + *d->process << "-y" << "null,null" << "-o" << "/dev/null"; + + // analyze the first 200 frames + *d->process << "-J" << QString("detectclipping=range=0-%1/5").arg(d->currentFrames); + + // also only decode the first 200 frames + *d->process << "-c" << QString("0-%1").arg(d->currentFrames+1); + + // additional user parameters from config + const QStringList& params = d->usedTranscodeBin->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *d->process << *it; + + // produce some debugging output + kdDebug() << "***** transcode parameters:\n"; + const QValueList& args = d->process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << flush << endl; + emit debuggingOutput( d->usedTranscodeBin->name() + " command:", s); + + // start the process + if( !d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) { + // something went wrong when starting the program + // it "should" be the executable + emit infoMessage( i18n("Could not start %1.").arg(d->usedTranscodeBin->name()), K3bJob::ERROR ); + jobFinished(false); + } + else { + emit newSubTask( i18n("Analysing Chapter %1 of %2").arg(chapter).arg(m_dvd[m_titleNumber-1].numPTTs()) ); + emit subPercent( 0 ); + } +} + + +void K3bVideoDVDTitleDetectClippingJob::cancel() +{ + d->canceled = true; + if( d->process && d->process->isRunning() ) + d->process->kill(); +} + + +void K3bVideoDVDTitleDetectClippingJob::slotTranscodeStderr( const QString& line ) +{ + emit debuggingOutput( "transcode", line ); + + // parse progress + // encoding frame [185], 24.02 fps, 93.0%, ETA: 0:00:00, ( 0| 0| 0) + if( line.startsWith( "encoding frame" ) ) { + int pos1 = line.find( '[', 15 ); + int pos2 = line.find( ']', pos1+1 ); + if( pos1 > 0 && pos2 > 0 ) { + bool ok; + int encodedFrames = line.mid( pos1+1, pos2-pos1-1 ).toInt( &ok ); + if( ok ) { + int progress = 100 * encodedFrames / d->currentFrames; + + if( progress > d->lastSubProgress ) { + d->lastSubProgress = progress; + emit subPercent( progress ); + } + + double part = 100.0 / (double)d->totalChapters; + + progress = (int)( ( (double)(d->currentChapter-1) * part ) + + ( (double)progress / (double)d->totalChapters ) + + 0.5 ); + + if( progress > d->lastProgress ) { + d->lastProgress = progress; + emit percent( progress ); + } + } + } + } + + // [detectclipping#0] valid area: X: 5..719 Y: 72..507 -> -j 72,6,68,0 + else if( line.startsWith( "[detectclipping" ) ) { + int pos = line.find( "-j" ); + if( pos > 0 ) { + QStringList values = QStringList::split( ',', line.mid( pos+3 ) ); + m_clippingTop = QMIN( m_clippingTop, values[0].toInt() ); + m_clippingLeft = QMIN( m_clippingLeft, values[1].toInt() ); + m_clippingBottom = QMIN( m_clippingBottom, values[2].toInt() ); + m_clippingRight = QMIN( m_clippingRight, values[3].toInt() ); + } + else + kdDebug() << "(K3bVideoDVDTitleDetectClippingJob) failed to parse line: " << line << endl; + } +} + + +void K3bVideoDVDTitleDetectClippingJob::slotTranscodeExited( KProcess* p ) +{ + switch( p->exitStatus() ) { + case 0: + d->currentChapter++; + if( d->currentChapter > d->totalChapters ) { + // + // check if we did set any values at all + // + if( m_clippingTop == s_unrealisticHighClippingValue ) + m_clippingTop = m_clippingLeft = m_clippingBottom = m_clippingRight = 0; + + if( d->totalChapters < m_dvd[m_titleNumber-1].numPTTs() ) + emit infoMessage( i18n("Ignoring last chapter due to its short playback time."), INFO ); + + jobFinished( true ); + } + else { + startTranscode( d->currentChapter ); + } + break; + + default: + // FIXME: error handling + + if( d->canceled ) { + emit canceled(); + } + else { + emit infoMessage( i18n("%1 returned an unknown error (code %2).") + .arg(d->usedTranscodeBin->name()).arg(p->exitStatus()), + K3bJob::ERROR ); + emit infoMessage( i18n("Please send me an email with the last output."), K3bJob::ERROR ); + } + + jobFinished( false ); + } +} + +#include "k3bvideodvdtitledetectclippingjob.moc" diff --git a/libk3b/jobs/k3bvideodvdtitledetectclippingjob.h b/libk3b/jobs/k3bvideodvdtitledetectclippingjob.h new file mode 100644 index 0000000..b13bbf8 --- /dev/null +++ b/libk3b/jobs/k3bvideodvdtitledetectclippingjob.h @@ -0,0 +1,106 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VIDEODVD_TITLE_DETECTCLIPPING_JOB_H_ +#define _K3B_VIDEODVD_TITLE_DETECTCLIPPING_JOB_H_ + +#include +#include +#include + +class KProcess; + +/** + * Job to detect the clipping values for a Video DVD title. + */ +class LIBK3B_EXPORT K3bVideoDVDTitleDetectClippingJob : public K3bJob +{ + Q_OBJECT + + public: + K3bVideoDVDTitleDetectClippingJob( K3bJobHandler* hdl, QObject* parent ); + ~K3bVideoDVDTitleDetectClippingJob(); + + const K3bVideoDVD::VideoDVD& videoDVD() const { return m_dvd; } + int title() const { return m_titleNumber; } + bool lowPriority() const { return m_lowPriority; } + + /** + * Only valid after a successful completion of the job. + */ + int clippingTop() const { return m_clippingTop; } + + /** + * Only valid after a successful completion of the job. + */ + int clippingLeft() const { return m_clippingLeft; } + + /** + * Only valid after a successful completion of the job. + */ + int clippingBottom() const { return m_clippingBottom; } + + /** + * Only valid after a successful completion of the job. + */ + int clippingRight() const { return m_clippingRight; } + + public slots: + void start(); + void cancel(); + + /** + * The device containing the Video DVD + */ + void setVideoDVD( const K3bVideoDVD::VideoDVD& dvd ) { m_dvd = dvd; } + + /** + * Set the title number to be analysed + * + * The default value is 1, denoting the first title. + */ + void setTitle( int t ) { m_titleNumber = t; } + + /** + * If true the transcode processes will be run with a very low scheduling + * priority. + * + * The default is true. + */ + void setLowPriority( bool b ) { m_lowPriority = b; } + + private slots: + void slotTranscodeStderr( const QString& ); + void slotTranscodeExited( KProcess* ); + + private: + void startTranscode( int chapter ); + + K3bVideoDVD::VideoDVD m_dvd; + + int m_clippingTop; + int m_clippingBottom; + int m_clippingLeft; + int m_clippingRight; + + int m_titleNumber; + + bool m_lowPriority; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/jobs/k3bvideodvdtitletranscodingjob.cpp b/libk3b/jobs/k3bvideodvdtitletranscodingjob.cpp new file mode 100644 index 0000000..9fec637 --- /dev/null +++ b/libk3b/jobs/k3bvideodvdtitletranscodingjob.cpp @@ -0,0 +1,583 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bvideodvdtitletranscodingjob.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + + +class K3bVideoDVDTitleTranscodingJob::Private +{ +public: + const K3bExternalBin* usedTranscodeBin; + + K3bProcess* process; + + QString twoPassEncodingLogFile; + + int currentEncodingPass; + + bool canceled; + + int lastProgress; + int lastSubProgress; +}; + + + +K3bVideoDVDTitleTranscodingJob::K3bVideoDVDTitleTranscodingJob( K3bJobHandler* hdl, QObject* parent ) + : K3bJob( hdl, parent ), + m_clippingTop( 0 ), + m_clippingBottom( 0 ), + m_clippingLeft( 0 ), + m_clippingRight( 0 ), + m_width( 0 ), + m_height( 0 ), + m_titleNumber( 1 ), + m_audioStreamIndex( 0 ), + m_videoCodec( VIDEO_CODEC_FFMPEG_MPEG4 ), + m_audioCodec( AUDIO_CODEC_MP3 ), + m_videoBitrate( 1800 ), + m_audioBitrate( 128 ), + m_audioVBR( false ), + m_resampleAudio( false ), + m_twoPassEncoding( false ), + m_lowPriority( true ) +{ + d = new Private; + d->process = 0; +} + + +K3bVideoDVDTitleTranscodingJob::~K3bVideoDVDTitleTranscodingJob() +{ + delete d->process; + delete d; +} + + +void K3bVideoDVDTitleTranscodingJob::start() +{ + jobStarted(); + + d->canceled = false; + d->lastProgress = 0; + + d->usedTranscodeBin = k3bcore->externalBinManager()->binObject("transcode"); + if( !d->usedTranscodeBin ) { + emit infoMessage( i18n("%1 executable could not be found.").arg("transcode"), ERROR ); + jobFinished( false ); + return; + } + + if( d->usedTranscodeBin->version < K3bVersion( 1, 0, 0 ) ){ + emit infoMessage( i18n("%1 version %2 is too old.") + .arg("transcode") + .arg(d->usedTranscodeBin->version), ERROR ); + jobFinished( false ); + return; + } + + emit debuggingOutput( "Used versions", "transcode: " + d->usedTranscodeBin->version ); + + if( !d->usedTranscodeBin->copyright.isEmpty() ) + emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3") + .arg(d->usedTranscodeBin->name()) + .arg(d->usedTranscodeBin->version) + .arg(d->usedTranscodeBin->copyright), INFO ); + + // + // Let's take a look at the filename + // + if( m_filename.isEmpty() ) { + m_filename = K3b::findTempFile( "avi" ); + } + else { + // let's see if the directory exists and we can write to it + QFileInfo fileInfo( m_filename ); + QFileInfo dirInfo( fileInfo.dirPath() ); + if( !dirInfo.exists() && !KStandardDirs::makeDir( dirInfo.absFilePath() ) ) { + emit infoMessage( i18n("Unable to create folder '%1'").arg(dirInfo.filePath()), ERROR ); + return; + } + else if( !dirInfo.isDir() || !dirInfo.isWritable() ) { + emit infoMessage( i18n("Invalid filename: '%1'").arg(m_filename), ERROR ); + jobFinished( false ); + return; + } + } + + // + // Determine a log file for two-pass encoding + // + d->twoPassEncodingLogFile = K3b::findTempFile( "log" ); + + emit newTask( i18n("Transcoding title %1 from Video DVD %2").arg(m_titleNumber).arg(m_dvd.volumeIdentifier()) ); + + // + // Ok then, let's begin + // + startTranscode( m_twoPassEncoding ? 1 : 0 ); +} + + +void K3bVideoDVDTitleTranscodingJob::startTranscode( int pass ) +{ + d->currentEncodingPass = pass; + d->lastSubProgress = 0; + + QString videoCodecString; + switch( m_videoCodec ) { + case VIDEO_CODEC_XVID: + videoCodecString = "xvid"; + break; + + case VIDEO_CODEC_FFMPEG_MPEG4: + videoCodecString = "ffmpeg"; + break; + + default: + emit infoMessage( i18n("Invalid Video codec set: %1").arg(m_videoCodec), ERROR ); + jobFinished( false ); + return; + } + + QString audioCodecString; + switch( m_audioCodec ) { + case AUDIO_CODEC_MP3: + audioCodecString = "0x55"; + break; + + // ogg only works (as in: transcode does something) with .y ,ogg + // but then the video is garbage (at least to xine and mplayer on my system) + // case AUDIO_CODEC_OGG_VORBIS: + // audioCodecString = "0xfffe"; + // break; + + case AUDIO_CODEC_AC3_STEREO: + case AUDIO_CODEC_AC3_PASSTHROUGH: + audioCodecString = "0x2000"; + break; + + default: + emit infoMessage( i18n("Invalid Audio codec set: %1").arg(m_audioCodec), ERROR ); + jobFinished( false ); + return; + } + + // + // prepare the process + // + delete d->process; + d->process = new K3bProcess(); + d->process->setSuppressEmptyLines(true); + d->process->setSplitStdout(true); + connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotTranscodeStderr(const QString&)) ); + connect( d->process, SIGNAL(stdoutLine(const QString&)), this, SLOT(slotTranscodeStderr(const QString&)) ); + connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotTranscodeExited(KProcess*)) ); + + // the executable + *d->process << d->usedTranscodeBin; + + // low priority + if( m_lowPriority ) + *d->process << "--nice" << "19"; + + // we only need 100 steps, but to make sure we use 150 + if ( d->usedTranscodeBin->version.simplify() >= K3bVersion( 1, 1, 0 ) ) + *d->process << "--progress_meter" << "2" << "--progress_rate" << QString::number(m_dvd[m_titleNumber-1].playbackTime().totalFrames()/150); + else + *d->process << "--print_status" << QString::number(m_dvd[m_titleNumber-1].playbackTime().totalFrames()/150); + + // the input + *d->process << "-i" << m_dvd.device()->blockDeviceName(); + + // just to make sure + *d->process << "-x" << "dvd"; + + // select the title number + *d->process << "-T" << QString("%1,-1,1").arg( m_titleNumber ); + + // select the audio stream to extract + if ( m_dvd[m_titleNumber-1].numAudioStreams() > 0 ) + *d->process << "-a" << QString::number( m_audioStreamIndex ); + + // clipping + *d->process << "-j" << QString("%1,%2,%3,%4") + .arg(m_clippingTop) + .arg(m_clippingLeft) + .arg(m_clippingBottom) + .arg(m_clippingRight); + + // select the encoding type (single pass or two-pass) and the log file for two-pass encoding + // the latter is unused for pass = 0 + *d->process << "-R" << QString("%1,%2").arg( pass ).arg( d->twoPassEncodingLogFile ); + + // depending on the pass we use different options + if( pass != 1 ) { + // select video codec + *d->process << "-y" << videoCodecString; + + // select the audio codec to use + *d->process << "-N" << audioCodecString; + + if( m_audioCodec == AUDIO_CODEC_AC3_PASSTHROUGH ) { + // keep 5.1 sound + *d->process << "-A"; + } + else { + // audio quality settings + *d->process << "-b" << QString("%1,%2").arg(m_audioBitrate).arg(m_audioVBR ? 1 : 0); + + // resample audio stream to 44.1 khz + if( m_resampleAudio ) + *d->process << "-E" << "44100"; + } + + // the output filename + *d->process << "-o" << m_filename; + } + else { + // gather information about the video stream, ignore audio + *d->process << "-y" << QString("%1,null").arg( videoCodecString ); + + // we ignore the output from the first pass + *d->process << "-o" << "/dev/null"; + } + + // choose the ffmpeg codec + if( m_videoCodec == VIDEO_CODEC_FFMPEG_MPEG4 ) { + *d->process << "-F" << "mpeg4"; + } + + // video bitrate + *d->process << "-w" << QString::number( m_videoBitrate ); + + // video resizing + int usedWidth = m_width; + int usedHeight = m_height; + if( m_width == 0 || m_height == 0 ) { + // + // The "real" size of the video, considering anamorph encoding + // + int realHeight = m_dvd[m_titleNumber-1].videoStream().realPictureHeight(); + int readWidth = m_dvd[m_titleNumber-1].videoStream().realPictureWidth(); + + // + // The clipped size with the correct aspect ratio + // + int clippedHeight = realHeight - m_clippingTop - m_clippingBottom; + int clippedWidth = readWidth - m_clippingLeft - m_clippingRight; + + // + // Now simply resize the clipped video to the wanted size + // + if( usedWidth > 0 ) { + usedHeight = clippedHeight * usedWidth / clippedWidth; + } + else { + if( usedHeight == 0 ) { + // + // This is the default case in which both m_width and m_height are 0. + // The result will be a size of clippedWidth x clippedHeight + // + usedHeight = clippedHeight; + } + usedWidth = clippedWidth * usedHeight / clippedHeight; + } + } + + // + // Now make sure both width and height are multiple of 16 the simple way + // + usedWidth -= usedWidth%16; + usedHeight -= usedHeight%16; + + // we only give information about the resizing of the video once + if( pass < 2 ) + emit infoMessage( i18n("Resizing picture of title %1 to %2x%3").arg(m_titleNumber).arg(usedWidth).arg(usedHeight), INFO ); + *d->process << "-Z" << QString("%1x%2").arg(usedWidth).arg(usedHeight); + + // additional user parameters from config + const QStringList& params = d->usedTranscodeBin->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *d->process << *it; + + // produce some debugging output + kdDebug() << "***** transcode parameters:\n"; + const QValueList& args = d->process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << flush << endl; + emit debuggingOutput( d->usedTranscodeBin->name() + " command:", s); + + // start the process + if( !d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) { + // something went wrong when starting the program + // it "should" be the executable + emit infoMessage( i18n("Could not start %1.").arg(d->usedTranscodeBin->name()), K3bJob::ERROR ); + jobFinished(false); + } + else { + if( pass == 0 ) + emit newSubTask( i18n("Single-pass Encoding") ); + else if( pass == 1 ) + emit newSubTask( i18n("Two-pass Encoding: First Pass") ); + else + emit newSubTask( i18n("Two-pass Encoding: Second Pass") ); + + emit subPercent( 0 ); + } +} + + +void K3bVideoDVDTitleTranscodingJob::cancel() +{ + // FIXME: do not cancel before one frame has been encoded. transcode seems to hang then + // find a way to determine all subprocess ids to kill all of them + d->canceled = true; + if( d->process && d->process->isRunning() ) + d->process->kill(); +} + + +void K3bVideoDVDTitleTranscodingJob::cleanup( bool success ) +{ + if( QFile::exists( d->twoPassEncodingLogFile ) ) { + QFile::remove( d->twoPassEncodingLogFile ); + } + + if( !success && QFile::exists( m_filename ) ) { + emit infoMessage( i18n("Removing incomplete video file '%1'").arg(m_filename), INFO ); + QFile::remove( m_filename ); + } +} + + +void K3bVideoDVDTitleTranscodingJob::slotTranscodeStderr( const QString& line ) +{ + emit debuggingOutput( "transcode", line ); + + // parse progress + // encoding frames [000000-000144], 27.58 fps, EMT: 0:00:05, ( 0| 0| 0) + if( line.startsWith( "encoding frame" ) ) { + int pos1 = line.find( '-', 15 ); + int pos2 = line.find( ']', pos1+1 ); + if( pos1 > 0 && pos2 > 0 ) { + bool ok; + int encodedFrames = line.mid( pos1+1, pos2-pos1-1 ).toInt( &ok ); + if( ok ) { + int progress = 100 * encodedFrames / m_dvd[m_titleNumber-1].playbackTime().totalFrames(); + + if( progress > d->lastSubProgress ) { + d->lastSubProgress = progress; + emit subPercent( progress ); + } + + if( m_twoPassEncoding ) { + progress /= 2; + if( d->currentEncodingPass == 2 ) + progress += 50; + } + + if( progress > d->lastProgress ) { + d->lastProgress = progress; + emit percent( progress ); + } + } + } + } +} + + +void K3bVideoDVDTitleTranscodingJob::slotTranscodeExited( KProcess* p ) +{ + if( d->canceled ) { + emit canceled(); + cleanup( false ); + jobFinished( false ); + } + else if( p->normalExit() ) { + switch( p->exitStatus() ) { + case 0: + if( d->currentEncodingPass == 1 ) { + emit percent( 50 ); + // start second encoding pass + startTranscode( 2 ); + } + else { + emit percent( 100 ); + cleanup( true ); + jobFinished( true ); + } + break; + + default: + // FIXME: error handling + + emit infoMessage( i18n("%1 returned an unknown error (code %2).") + .arg(d->usedTranscodeBin->name()).arg(p->exitStatus()), + K3bJob::ERROR ); + emit infoMessage( i18n("Please send me an email with the last output."), K3bJob::ERROR ); + + cleanup( false ); + jobFinished( false ); + } + } + else { + cleanup( false ); + emit infoMessage( i18n("Execution of %1 failed.").arg("transcode"), ERROR ); + emit infoMessage( i18n("Please consult the debugging output for details."), ERROR ); + jobFinished( false ); + } +} + + +void K3bVideoDVDTitleTranscodingJob::setClipping( int top, int left, int bottom, int right ) +{ + m_clippingTop = top; + m_clippingLeft = left; + m_clippingBottom = bottom; + m_clippingRight = right; + + // + // transcode seems unable to handle different clipping values for left and right + // + m_clippingLeft = m_clippingRight = QMIN( m_clippingRight, m_clippingLeft ); +} + + +void K3bVideoDVDTitleTranscodingJob::setSize( int width, int height ) +{ + m_width = width; + m_height = height; +} + + +QString K3bVideoDVDTitleTranscodingJob::audioCodecString( K3bVideoDVDTitleTranscodingJob::AudioCodec codec ) +{ + switch( codec ) { + case AUDIO_CODEC_AC3_STEREO: + return i18n("AC3 (Stereo)"); + case AUDIO_CODEC_AC3_PASSTHROUGH: + return i18n("AC3 (Pass-through)"); + case AUDIO_CODEC_MP3: + return i18n("MPEG1 Layer III"); + default: + return "unknown audio codec"; + } +} + + +QString K3bVideoDVDTitleTranscodingJob::videoCodecString( K3bVideoDVDTitleTranscodingJob::VideoCodec codec ) +{ + switch( codec ) { + case VIDEO_CODEC_FFMPEG_MPEG4: + return i18n("MPEG4 (FFMPEG)"); + case VIDEO_CODEC_XVID: + return i18n("XviD"); + default: + return "unknown video codec"; + } +} + + +QString K3bVideoDVDTitleTranscodingJob::videoCodecDescription( K3bVideoDVDTitleTranscodingJob::VideoCodec codec ) +{ + switch( codec ) { + case VIDEO_CODEC_FFMPEG_MPEG4: + return i18n("FFmpeg is an open-source project trying to support most video and audio codecs used " + "these days. Its subproject libavcodec forms the basis for multimedia players such as " + "xine or mplayer.") + + "
" + + i18n("FFmpeg contains an implementation of the MPEG-4 video encoding standard which produces " + "high quality results."); + case VIDEO_CODEC_XVID: + return i18n("XviD is a free and open source MPEG-4 video codec. XviD was created by a group of " + "volunteer programmers after the OpenDivX source was closed in July 2001.") + + "
" + + i18n("XviD features MPEG-4 Advanced Profile settings such as b-frames, global " + "and quarter pixel motion compensation, lumi masking, trellis quantization, and " + "H.263, MPEG and custom quantization matrices.") + + "
" + + i18n("XviD is a primary competitor of DivX (XviD being DivX spelled backwards). " + "While DivX is closed source and may only run on Windows, Mac OS and Linux, " + "XviD is open source and can potentially run on any platform.") + + "
" + + i18n("(Description taken from the Wikipedia article)") + + ""; + default: + return "unknown video codec"; + } +} + + +QString K3bVideoDVDTitleTranscodingJob::audioCodecDescription( K3bVideoDVDTitleTranscodingJob::AudioCodec codec ) +{ + static QString s_ac3General = i18n("AC3, better known as Dolby Digital is standardized as ATSC A/52. " + "It contains up to 6 total channels of sound."); + switch( codec ) { + case AUDIO_CODEC_AC3_STEREO: + return s_ac3General + + "
" + i18n("With this setting K3b will create a two-channel stereo " + "Dolby Digital audio stream."); + case AUDIO_CODEC_AC3_PASSTHROUGH: + return s_ac3General + + "
" + i18n("With this setting K3b will use the Dolby Digital audio stream " + "from the source DVD without changing it.") + + "
" + i18n("Use this setting to preserve 5.1 channel sound from the DVD."); + case AUDIO_CODEC_MP3: + return i18n("MPEG1 Layer III is better known as MP3 and is the most used lossy audio format.") + + "
" + i18n("With this setting K3b will create a two-channel stereo MPEG1 Layer III audio stream."); + default: + return "unknown audio codec"; + } +} + + +bool K3bVideoDVDTitleTranscodingJob::transcodeBinaryHasSupportFor( K3bVideoDVDTitleTranscodingJob::VideoCodec codec, const K3bExternalBin* bin ) +{ + static char* s_codecFeatures[] = { "xvid", "ffmpeg" }; + if( !bin ) + bin = k3bcore->externalBinManager()->binObject("transcode"); + if( !bin ) + return false; + return bin->hasFeature( QString::fromLatin1( s_codecFeatures[(int)codec] ) ); +} + + +bool K3bVideoDVDTitleTranscodingJob::transcodeBinaryHasSupportFor( K3bVideoDVDTitleTranscodingJob::AudioCodec codec, const K3bExternalBin* bin ) +{ + static char* s_codecFeatures[] = { "lame", "ac3", "ac3" }; + if( !bin ) + bin = k3bcore->externalBinManager()->binObject("transcode"); + if( !bin ) + return false; + return bin->hasFeature( QString::fromLatin1( s_codecFeatures[(int)codec] ) ); +} + +#include "k3bvideodvdtitletranscodingjob.moc" diff --git a/libk3b/jobs/k3bvideodvdtitletranscodingjob.h b/libk3b/jobs/k3bvideodvdtitletranscodingjob.h new file mode 100644 index 0000000..77a48b5 --- /dev/null +++ b/libk3b/jobs/k3bvideodvdtitletranscodingjob.h @@ -0,0 +1,275 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VIDEODVD_TITLE_TRANSCODING_JOB_H_ +#define _K3B_VIDEODVD_TITLE_TRANSCODING_JOB_H_ + +#include +#include +#include + +class KProcess; +class K3bExternalBin; + + +/** + * The K3bVideoDVDTitleTranscodingJob rips a Video DVD title directly + * from the medium and transcodes it on-the-fly to, for example, an XviD video + * + * For now only one audio stream is supported. + */ +class LIBK3B_EXPORT K3bVideoDVDTitleTranscodingJob : public K3bJob +{ + Q_OBJECT + + public: + K3bVideoDVDTitleTranscodingJob( K3bJobHandler* hdl, QObject* parent ); + ~K3bVideoDVDTitleTranscodingJob(); + + /** + * The video codecs supported by this job. + */ + enum VideoCodec { + VIDEO_CODEC_XVID, + VIDEO_CODEC_FFMPEG_MPEG4, + VIDEO_CODEC_NUM_ENTRIES /**< Do not use this as a codec. */ + }; + + /** + * The audio codecs supported by this job. + */ + enum AudioCodec { + AUDIO_CODEC_MP3, + /* AUDIO_CODEC_OGG_VORBIS,*/ + AUDIO_CODEC_AC3_STEREO, + AUDIO_CODEC_AC3_PASSTHROUGH, + AUDIO_CODEC_NUM_ENTRIES /**< Do not use this as a codec. */ + }; + + const K3bVideoDVD::VideoDVD& videoDVD() const { return m_dvd; } + int title() const { return m_titleNumber; } + int audioStream() const { return m_audioStreamIndex; } + int clippingTop() const { return m_clippingTop; } + int clippingLeft() const { return m_clippingLeft; } + int clippingBottom() const { return m_clippingBottom; } + int clippingRight() const { return m_clippingRight; } + int height() const { return m_height; } + int width() const { return m_width; } + const QString& filename() { return m_filename; } + VideoCodec videoCodec() const { return m_videoCodec; } + int videoBitrate() const { return m_videoBitrate; } + bool twoPassEncoding() const { return m_twoPassEncoding; } + AudioCodec audioCodec() const { return m_audioCodec; } + int audioBitrate() const { return m_audioBitrate; } + bool audioVBR() const { return m_audioVBR; } + bool resampleAudioTo44100() const { return m_resampleAudio; } + bool lowPriority() const { return m_lowPriority; } + + /** + * \param bin If 0 the default binary from K3bCore will be used + */ + static bool transcodeBinaryHasSupportFor( VideoCodec codec, const K3bExternalBin* bin = 0 ); + + /** + * \param bin If 0 the default binary from K3bCore will be used + */ + static bool transcodeBinaryHasSupportFor( AudioCodec codec, const K3bExternalBin* bin = 0 ); + + static QString videoCodecString( VideoCodec ); + static QString audioCodecString( AudioCodec ); + + static QString videoCodecDescription( VideoCodec ); + static QString audioCodecDescription( AudioCodec ); + + public slots: + void start(); + void cancel(); + + /** + * The device containing the Video DVD + */ + void setVideoDVD( const K3bVideoDVD::VideoDVD& dvd ) { m_dvd = dvd; } + + /** + * Set the title number to be transcoded + * + * The default value is 1, denoting the first title. + */ + void setTitle( int t ) { m_titleNumber = t; } + + /** + * Set the audio stream to use. + * + * For now K3b does not support encoding multiple audio streams + * in one video file. + * + * The default value is 0, meaning that the first audio stream will + * be encoded. + */ + void setAudioStream( int i ) { m_audioStreamIndex = i; } + + /** + * Set the clipping values for the Video title. + * The clipping will be applied before the transcoding. + * + * For now it is not possible to use different clipping values for left + * and right as transcode cannot handle this. Thus, the job uses the + * smaller value for both the left and right clipping. + * + * The default is to not clip the video. + */ + void setClipping( int top, int left, int bottom, int right ); + + /** + * The size of the resulting transcoded video. + * + * The default is to automatically adjust the size (width=height=0), which + * essentially means that anamorph encoded source material will be resized + * according to its aspect ratio. + * + * It is also possible to set just the width or just the height and leave + * the other value to 0 which will then be determined automatically. + * + * The clipping values will be taken into account if at least one value + * is determined automatically. + * + * The width and height values have to be a multiple of 16. If it is not, + * they will be changed accordingly. + * + * FIXME: GET INFORMATION: why a multiple of 16 and not 8 or 32? + */ + void setSize( int width, int height ); + + /** + * The filename to write the resulting video to. + * + * The default is some automatically generated filename + * in the default K3b temp directory. + */ + void setFilename( const QString& name ) { m_filename = name; } + + /** + * Set the video codec used to encode the video title. + * + * The default is VIDEO_CODEC_FFMPEG_MPEG4 + */ + void setVideoCodec( VideoCodec codec ) { m_videoCodec = codec; } + + /** + * Set the bitrate used to encode the video. + * + * The default is 1800 + */ + void setVideoBitrate( int bitrate ) { m_videoBitrate = bitrate; } + + /** + * Set if the job should use two-pass encoding to improve + * the quality of the resulting video. + * + * The default is false. + */ + void setTwoPassEncoding( bool b ) { m_twoPassEncoding = b; } + + /** + * Set the audio codec used to encode the audio stream + * in the video title. + * + * The default is AUDIO_CODEC_MP3 + */ + void setAudioCodec( AudioCodec codec ) { m_audioCodec = codec; } + + /** + * Set the bitrate used to encode the audio stream. + * + * The default is 128 + * + * In case of the AC3 codec the bitrate can be some value between 32 and 640. + * + * For the AC3 passthrough mode the bitrate is ignored. + */ + void setAudioBitrate( int bitrate ) { m_audioBitrate = bitrate; } + + /** + * Set if the audio stream should be encoded with a variable bitrate. + * + * The default is false. + * + * For the AC3 passthrough mode the bitrate is ignored. + */ + void setAudioVBR( bool vbr ) { m_audioVBR = vbr; } + + /** + * Set if the audio data should be resampled to 44100 Hz/s + * + * The default is false. + * + * For the AC3 passthrough mode this is ignored. + */ + void setResampleAudioTo44100( bool b ) { m_resampleAudio = b; } + + /** + * If true the transcode processes will be run with a very low scheduling + * priority. + * + * The default is true. + */ + void setLowPriority( bool b ) { m_lowPriority = b; } + + private slots: + void slotTranscodeStderr( const QString& ); + void slotTranscodeExited( KProcess* ); + + private: + /** + * \param 0 - single pass encoding + * 1 - two pass encoding/first pass + * 2 - two pass encoding/second pass + */ + void startTranscode( int pass ); + + void cleanup( bool success ); + + K3bVideoDVD::VideoDVD m_dvd; + + QString m_filename; + + int m_clippingTop; + int m_clippingBottom; + int m_clippingLeft; + int m_clippingRight; + + int m_width; + int m_height; + + int m_titleNumber; + int m_audioStreamIndex; + + VideoCodec m_videoCodec; + AudioCodec m_audioCodec; + + int m_videoBitrate; + int m_audioBitrate; + bool m_audioVBR; + + bool m_resampleAudio; + bool m_twoPassEncoding; + + bool m_lowPriority; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/k3bimage.xsd b/libk3b/k3bimage.xsd new file mode 100644 index 0000000..ab7f36c --- /dev/null +++ b/libk3b/k3bimage.xsd @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libk3b/plugin/Makefile.am b/libk3b/plugin/Makefile.am new file mode 100644 index 0000000..49ac69b --- /dev/null +++ b/libk3b/plugin/Makefile.am @@ -0,0 +1,28 @@ +if compile_libsamplerate +USED_LIBSAMPLERATE=./libsamplerate/libsamplerate.la +SUBDIRS = libsamplerate +else +USED_LIBSAMPLERATE=$(LIBSAMPLERATE) +endif + + +AM_CPPFLAGS = -I$(srcdir)/.. -I$(srcdir)/../core/ -I$(srcdir)/../../src -I$(srcdir)/../../libk3bdevice $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libk3bplugin.la + +libk3bplugin_la_LIBADD = $(USED_LIBSAMPLERATE) + +libk3bplugin_la_LDFLAGS = $(all_libraries) + +libk3bplugin_la_SOURCES = k3bplugin.cpp \ + k3bpluginconfigwidget.cpp \ + k3bpluginmanager.cpp \ + k3baudiodecoder.cpp \ + k3baudioencoder.cpp \ + k3baudioclient.cpp \ + k3baudioserver.cpp + + +include_HEADERS = k3bplugin.h k3bpluginfactory.h k3bpluginmanager.h k3baudiodecoder.h k3baudioencoder.h k3bpluginconfigwidget.h k3baudiooutputplugin.h k3bprojectplugin.h diff --git a/libk3b/plugin/k3baudioclient.cpp b/libk3b/plugin/k3baudioclient.cpp new file mode 100644 index 0000000..5133d28 --- /dev/null +++ b/libk3b/plugin/k3baudioclient.cpp @@ -0,0 +1,46 @@ +/* + * + * $Id: k3baudioclient.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudioclient.h" +#include "k3baudioserver.h" + + +K3bAudioClient::K3bAudioClient() + : m_attached(false) +{ +} + + +K3bAudioClient::~K3bAudioClient() +{ +} + + +void K3bAudioClient::startStreaming() +{ + if( !m_attached ) { + K3bAudioServer::instance()->attachClient( this ); + m_attached = true; + } +} + + +void K3bAudioClient::stopStreaming() +{ + if( m_attached ) { + K3bAudioServer::instance()->detachClient( this ); + m_attached = false; + } +} diff --git a/libk3b/plugin/k3baudioclient.h b/libk3b/plugin/k3baudioclient.h new file mode 100644 index 0000000..9d6c015 --- /dev/null +++ b/libk3b/plugin/k3baudioclient.h @@ -0,0 +1,51 @@ +/* + * + * $Id: k3baudioclient.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_CLIENT_H_ +#define _K3B_AUDIO_CLIENT_H_ + +#include "k3b_export.h" +/** + * Interface for all K3b audio client classes which may attach to + * a K3b Audio Server to play 44100 16bit stereo audio data. + */ +class LIBK3B_EXPORT K3bAudioClient +{ + public: + virtual ~K3bAudioClient(); + + /** + * if this method returns a value below 0 streaming is stopped. + */ + virtual int read( char* data, int maxlen ) = 0; + + protected: + K3bAudioClient(); + + /** + * This will start the streaming. + */ + void startStreaming(); + + /** + * This stops the streaming, + */ + void stopStreaming(); + + private: + bool m_attached; +}; + +#endif diff --git a/libk3b/plugin/k3baudiodecoder.cpp b/libk3b/plugin/k3baudiodecoder.cpp new file mode 100644 index 0000000..82f4adb --- /dev/null +++ b/libk3b/plugin/k3baudiodecoder.cpp @@ -0,0 +1,599 @@ +/* + * + * $Id: k3baudiodecoder.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include + +#include + +#include "k3baudiodecoder.h" +#include "k3bpluginmanager.h" + +#include +#include + +#include + +#include + +#ifdef HAVE_LIBSAMPLERATE +#include +#else +#include "libsamplerate/samplerate.h" +#endif + +#if !(HAVE_LRINT && HAVE_LRINTF) +#define lrint(dbl) ((int) (dbl)) +#define lrintf(flt) ((int) (flt)) +#endif + +// use a one second buffer +static const int DECODING_BUFFER_SIZE = 75*2352; + +class K3bAudioDecoder::Private +{ +public: + Private() + : metaInfo(0), + resampleState(0), + resampleData(0), + inBuffer(0), + inBufferPos(0), + inBufferFill(0), + outBuffer(0), + monoBuffer(0), + decodingBufferPos(0), + decodingBufferFill(0), + valid(true) { + } + + // the current position of the decoder + // This does NOT include the decodingBuffer + K3b::Msf currentPos; + + // since the current position above is measured in frames + // there might be a little offset since the decoded data is not + // always a multiple of 2353 bytes + int currentPosOffset; + + // already decoded bytes from last init or last seek + // TODO: replace alreadyDecoded with currentPos + unsigned long alreadyDecoded; + + K3b::Msf decodingStartPos; + + KFileMetaInfo* metaInfo; + + // set to true once decodeInternal() returned 0 + bool decoderFinished; + + // resampling + SRC_STATE* resampleState; + SRC_DATA* resampleData; + + float* inBuffer; + float* inBufferPos; + int inBufferFill; + + float* outBuffer; + + int samplerate; + int channels; + + // mono -> stereo conversion + char* monoBuffer; + + char decodingBuffer[DECODING_BUFFER_SIZE]; + char* decodingBufferPos; + int decodingBufferFill; + + QMap technicalInfoMap; + QMap metaInfoMap; + + bool valid; +}; + + + +K3bAudioDecoder::K3bAudioDecoder( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + d = new Private(); +} + + +K3bAudioDecoder::~K3bAudioDecoder() +{ + cleanup(); + + if( d->inBuffer ) delete [] d->inBuffer; + if( d->outBuffer ) delete [] d->outBuffer; + if( d->monoBuffer ) delete [] d->monoBuffer; + + delete d->metaInfo; + delete d->resampleData; + if( d->resampleState ) + src_delete( d->resampleState ); + delete d; +} + + +void K3bAudioDecoder::setFilename( const QString& filename ) +{ + m_fileName = filename; + delete d->metaInfo; + d->metaInfo = 0; +} + + +bool K3bAudioDecoder::isValid() const +{ + return d->valid; +} + + +bool K3bAudioDecoder::analyseFile() +{ + d->technicalInfoMap.clear(); + d->metaInfoMap.clear(); + delete d->metaInfo; + d->metaInfo = 0; + + cleanup(); + + bool ret = analyseFileInternal( m_length, d->samplerate, d->channels ); + if( ret && ( d->channels == 1 || d->channels == 2 ) && m_length > 0 ) { + d->valid = initDecoder(); + return d->valid; + } + else { + d->valid = false; + return false; + } +} + + +bool K3bAudioDecoder::initDecoder( const K3b::Msf& startOffset ) +{ + if( initDecoder() ) { + if( startOffset > 0 ) + return seek( startOffset ); + else + return true; + } + else + return false; +} + + +bool K3bAudioDecoder::initDecoder() +{ + cleanup(); + + if( d->resampleState ) + src_reset( d->resampleState ); + + d->alreadyDecoded = 0; + d->currentPos = 0; + d->currentPosOffset = 0; + d->decodingBufferFill = 0; + d->decodingBufferPos = 0; + d->decodingStartPos = 0; + d->inBufferFill = 0; + + d->decoderFinished = false; + + return initDecoderInternal(); +} + + +int K3bAudioDecoder::decode( char* _data, int maxLen ) +{ + unsigned long lengthToDecode = (m_length - d->decodingStartPos).audioBytes(); + + if( d->alreadyDecoded >= lengthToDecode ) + return 0; + + if( maxLen <= 0 ) + return 0; + + int read = 0; + + if( d->decodingBufferFill == 0 ) { + // + // now we decode into the decoding buffer + // to ensure a minimum buffer size + // + d->decodingBufferFill = 0; + d->decodingBufferPos = d->decodingBuffer; + + if( !d->decoderFinished ) { + if( d->samplerate != 44100 ) { + + // check if we have data left from some previous conversion + if( d->inBufferFill > 0 ) { + read = resample( d->decodingBuffer, DECODING_BUFFER_SIZE ); + } + else { + if( !d->inBuffer ) { + d->inBuffer = new float[DECODING_BUFFER_SIZE/2]; + } + + if( (read = decodeInternal( d->decodingBuffer, DECODING_BUFFER_SIZE )) == 0 ) + d->decoderFinished = true; + + d->inBufferFill = read/2; + d->inBufferPos = d->inBuffer; + from16bitBeSignedToFloat( d->decodingBuffer, d->inBuffer, d->inBufferFill ); + + read = resample( d->decodingBuffer, DECODING_BUFFER_SIZE ); + } + } + else if( d->channels == 1 ) { + if( !d->monoBuffer ) { + d->monoBuffer = new char[DECODING_BUFFER_SIZE/2]; + } + + // we simply duplicate every frame + if( (read = decodeInternal( d->monoBuffer, DECODING_BUFFER_SIZE/2 )) == 0 ) + d->decoderFinished = true; + + for( int i = 0; i < read; i+=2 ) { + d->decodingBuffer[2*i] = d->decodingBuffer[2*i+2] = d->monoBuffer[i]; + d->decodingBuffer[2*i+1] = d->decodingBuffer[2*i+3] = d->monoBuffer[i+1]; + } + + read *= 2; + } + else { + if( (read = decodeInternal( d->decodingBuffer, DECODING_BUFFER_SIZE )) == 0 ) + d->decoderFinished = true; + } + } + + if( read < 0 ) { + return -1; + } + else if( read == 0 ) { + // check if we need to pad + int bytesToPad = lengthToDecode - d->alreadyDecoded; + if( bytesToPad > 0 ) { + kdDebug() << "(K3bAudioDecoder) track length: " << lengthToDecode + << "; decoded module data: " << d->alreadyDecoded + << "; we need to pad " << bytesToPad << " bytes." << endl; + + if( DECODING_BUFFER_SIZE < bytesToPad ) + bytesToPad = DECODING_BUFFER_SIZE; + + ::memset( d->decodingBuffer, 0, bytesToPad ); + + kdDebug() << "(K3bAudioDecoder) padded " << bytesToPad << " bytes." << endl; + + read = bytesToPad; + } + else { + kdDebug() << "(K3bAudioDecoder) decoded " << d->alreadyDecoded << " bytes." << endl; + return 0; + } + } + else { + + // check if we decoded too much + if( d->alreadyDecoded + read > lengthToDecode ) { + kdDebug() << "(K3bAudioDecoder) we decoded too much. Cutting output by " + << (read + d->alreadyDecoded - lengthToDecode) << endl; + read = lengthToDecode - d->alreadyDecoded; + } + } + + d->decodingBufferFill = read; + } + + + // clear out the decoding buffer + read = QMIN( maxLen, d->decodingBufferFill ); + ::memcpy( _data, d->decodingBufferPos, read ); + d->decodingBufferPos += read; + d->decodingBufferFill -= read; + + d->alreadyDecoded += read; + d->currentPos += (read+d->currentPosOffset)/2352; + d->currentPosOffset = (read+d->currentPosOffset)%2352; + + return read; +} + + +// resample data in d->inBufferPos and save the result to data +// +// +int K3bAudioDecoder::resample( char* data, int maxLen ) +{ + if( !d->resampleState ) { + d->resampleState = src_new( SRC_SINC_MEDIUM_QUALITY, d->channels, 0 ); + if( !d->resampleState ) { + kdDebug() << "(K3bAudioDecoder) unable to initialize resampler." << endl; + return -1; + } + d->resampleData = new SRC_DATA; + } + + if( !d->outBuffer ) { + d->outBuffer = new float[DECODING_BUFFER_SIZE/2]; + } + + d->resampleData->data_in = d->inBufferPos; + d->resampleData->data_out = d->outBuffer; + d->resampleData->input_frames = d->inBufferFill/d->channels; + d->resampleData->output_frames = maxLen/2/2; // in case of mono files we need the space anyway + d->resampleData->src_ratio = 44100.0/(double)d->samplerate; + if( d->inBufferFill == 0 ) + d->resampleData->end_of_input = 1; // this should force libsamplerate to output the last frames + else + d->resampleData->end_of_input = 0; + + int len = 0; + if( (len = src_process( d->resampleState, d->resampleData ) ) ) { + kdDebug() << "(K3bAudioDecoder) error while resampling: " << src_strerror(len) << endl; + return -1; + } + + if( d->channels == 2 ) + fromFloatTo16BitBeSigned( d->outBuffer, data, d->resampleData->output_frames_gen*d->channels ); + else { + for( int i = 0; i < d->resampleData->output_frames_gen; ++i ) { + fromFloatTo16BitBeSigned( &d->outBuffer[i], &data[4*i], 1 ); + fromFloatTo16BitBeSigned( &d->outBuffer[i], &data[4*i+2], 1 ); + } + } + + d->inBufferPos += d->resampleData->input_frames_used*d->channels; + d->inBufferFill -= d->resampleData->input_frames_used*d->channels; + if( d->inBufferFill <= 0 ) { + d->inBufferPos = d->inBuffer; + d->inBufferFill = 0; + } + + // 16 bit frames, so we need to multiply by 2 + // and we always have two channels + return d->resampleData->output_frames_gen*2*2; +} + + +void K3bAudioDecoder::from16bitBeSignedToFloat( char* src, float* dest, int samples ) +{ + while( samples ) { + samples--; + dest[samples] = static_cast( Q_INT16(((src[2*samples]<<8)&0xff00)|(src[2*samples+1]&0x00ff)) / 32768.0 ); + } +} + + +void K3bAudioDecoder::fromFloatTo16BitBeSigned( float* src, char* dest, int samples ) +{ + while( samples ) { + samples--; + + float scaled = src[samples] * 32768.0; + Q_INT16 val = 0; + + // clipping + if( scaled >= ( 1.0 * 0x7FFF ) ) + val = 32767; + else if( scaled <= ( -8.0 * 0x1000 ) ) + val = -32768; + else + val = lrintf(scaled); + + dest[2*samples] = val>>8; + dest[2*samples+1] = val; + } +} + + +void K3bAudioDecoder::from8BitTo16BitBeSigned( char* src, char* dest, int samples ) +{ + while( samples ) { + samples--; + + float scaled = static_cast(Q_UINT8(src[samples])-128) / 128.0 * 32768.0; + Q_INT16 val = 0; + + // clipping + if( scaled >= ( 1.0 * 0x7FFF ) ) + val = 32767; + else if( scaled <= ( -8.0 * 0x1000 ) ) + val = -32768; + else + val = lrintf(scaled); + + dest[2*samples] = val>>8; + dest[2*samples+1] = val; + } +} + + +bool K3bAudioDecoder::seek( const K3b::Msf& pos ) +{ + kdDebug() << "(K3bAudioDecoder) seek from " << d->currentPos.toString() << " (+" << d->currentPosOffset + << ") to " << pos.toString() << endl; + + if( pos > length() ) + return false; + + d->decoderFinished = false; + + if( pos == d->currentPos && d->currentPosOffset == 0 ) + return true; + + if( pos == 0 ) + return initDecoder(); + + bool success = false; + + // + // First check if we may do a "perfect seek". + // We cannot rely on the decoding plugins to seek perfectly. Especially + // the mp3 decoder does not. But in case we want to split a live recording + // it is absolutely nesseccary to perform a perfect seek. + // So if we did not already decode past the seek position and the difference + // between the current position and the seek position is less than some fixed + // value we simply decode up to the seek position. + // + if( ( pos > d->currentPos || + ( pos == d->currentPos && d->currentPosOffset == 0 ) ) + && + ( pos - d->currentPos < K3b::Msf(0,10,0) ) ) { // < 10 seconds is ok + kdDebug() << "(K3bAudioDecoder) performing perfect seek from " << d->currentPos.toString() + << " to " << pos.toString() << ". :)" << endl; + + unsigned long bytesToDecode = pos.audioBytes() - d->currentPos.audioBytes() - d->currentPosOffset; + kdDebug() << "(K3bAudioDecoder) seeking " << bytesToDecode << " bytes." << endl; + char buffi[10*2352]; + while( bytesToDecode > 0 ) { + int read = decode( buffi, QMIN(10*2352, bytesToDecode) ); + if( read <= 0 ) + return false; + + bytesToDecode -= read; + } + + kdDebug() << "(K3bAudioDecoder) perfect seek done." << endl; + + success = true; + } + else { + // + // Here we have to reset the resampling stuff since we restart decoding at another position. + // + if( d->resampleState ) + src_reset( d->resampleState ); + d->inBufferFill = 0; + + // + // And also reset the decoding buffer to not return any garbage from previous decoding. + // + d->decodingBufferFill = 0; + + success = seekInternal( pos ); + } + + d->alreadyDecoded = 0; + d->currentPos = d->decodingStartPos = pos; + d->currentPosOffset = 0; + + return success; +} + + +void K3bAudioDecoder::cleanup() +{ +} + + +QString K3bAudioDecoder::metaInfo( MetaDataField f ) +{ + if( d->metaInfoMap.contains( f ) ) + return d->metaInfoMap[f]; + + // fall back to KFileMetaInfo + if( !d->metaInfo ) + d->metaInfo = new KFileMetaInfo( filename() ); + + if( d->metaInfo->isValid() ) { + QString tag; + switch( f ) { + case META_TITLE: + tag = "Title"; + break; + case META_ARTIST: + tag = "Artist"; + break; + case META_SONGWRITER: + tag = "Songwriter"; + break; + case META_COMPOSER: + tag = "Composer"; + break; + case META_COMMENT: + tag = "Comment"; + break; + } + + KFileMetaInfoItem item = d->metaInfo->item( tag ); + if( item.isValid() ) + return item.string(); + } + + return QString::null; +} + + +void K3bAudioDecoder::addMetaInfo( MetaDataField f, const QString& value ) +{ + if( !value.isEmpty() ) + d->metaInfoMap[f] = value; + else + kdDebug() << "(K3bAudioDecoder) empty meta data field." << endl; +} + + +QStringList K3bAudioDecoder::supportedTechnicalInfos() const +{ + QStringList l; + for( QMap::const_iterator it = d->technicalInfoMap.begin(); + it != d->technicalInfoMap.end(); ++it ) + l.append( it.key() ); + return l; +} + + +QString K3bAudioDecoder::technicalInfo( const QString& key ) const +{ + return d->technicalInfoMap[key]; +} + + +void K3bAudioDecoder::addTechnicalInfo( const QString& key, const QString& value ) +{ + d->technicalInfoMap[key] = value; +} + + +K3bAudioDecoder* K3bAudioDecoderFactory::createDecoder( const KURL& url ) +{ + kdDebug() << "(K3bAudioDecoderFactory::createDecoder( " << url.path() << " )" << endl; + QPtrList fl = k3bcore->pluginManager()->plugins( "AudioDecoder" ); + + // first search for a single format decoder + for( QPtrListIterator it( fl ); it.current(); ++it ) { + K3bAudioDecoderFactory* f = dynamic_cast( it.current() ); + if( f && !f->multiFormatDecoder() && f->canDecode( url ) ) { + kdDebug() << "1" << endl; return f->createDecoder();} + } + + // no single format decoder. Search for a multi format decoder + for( QPtrListIterator it( fl ); it.current(); ++it ) { + K3bAudioDecoderFactory* f = dynamic_cast( it.current() ); + if( f && f->multiFormatDecoder() && f->canDecode( url ) ) { + kdDebug() << "2" << endl; return f->createDecoder();} + } + + kdDebug() << "(K3bAudioDecoderFactory::createDecoder( " << url.path() << " ) no success" << endl; + + // nothing found + return 0; +} + +#include "k3baudiodecoder.moc" diff --git a/libk3b/plugin/k3baudiodecoder.h b/libk3b/plugin/k3baudiodecoder.h new file mode 100644 index 0000000..69f594c --- /dev/null +++ b/libk3b/plugin/k3baudiodecoder.h @@ -0,0 +1,254 @@ +/* + * + * $Id: k3baudiodecoder.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_DECODER_H_ +#define _K3B_AUDIO_DECODER_H_ + + +#include +#include +#include "k3b_export.h" +#include + + + +/** + * Abstract streaming class for all the audio input. + * Has to output data in the following format: + * MSBLeft LSBLeft MSBRight LSBRight (big endian byte order) + * + * Instances are created by K3bAudioDecoderFactory + **/ +class LIBK3B_EXPORT K3bAudioDecoder : public QObject +{ + Q_OBJECT + + public: + K3bAudioDecoder( QObject* parent = 0, const char* name = 0 ); + virtual ~K3bAudioDecoder(); + + + /** + * Set the file to decode. Be aware that one cannot rely + * on the file length until analyseFile() has been called. + */ + void setFilename( const QString& ); + + /** + * Since this may take a while depending on the filetype it is best + * to run it in a separate thread. + * + * This method will also call initDecoder(). + */ + bool analyseFile(); + + /** + * @return true if the file was successfully analysed by analyseFile. + */ + bool isValid() const; + + /** + * Initialize the decoding. + * Normally there is no need to call this as analyseFile already does so. + */ + bool initDecoder(); + + /** + * initialize the decoding. + * @param startOffset the number of frames to skip at the beginning of the file. + * + * This is the same as calling: initDecoder() and seek(startOffset) + */ + bool initDecoder( const K3b::Msf& startOffset ); + + enum MetaDataField { + META_TITLE, + META_ARTIST, + META_SONGWRITER, + META_COMPOSER, + META_COMMENT + }; + + /** + * This should at least support "Title" and "Artist" + * + * the default implementation returns the infos set via @p addMetaInfo + * and uses KFileMetaInfo if none was set + */ + virtual QString metaInfo( MetaDataField ); + + /** + * The filetype is only used for informational purposes. + * It is not necessary but highly recommended to implement this method + * as it enhances usability. + * @returne The filetype of the decoded file. + */ + virtual QString fileType() const { return QString::null; } + + /** + * This method may be reimplemented to provide technical information about + * the file. It should return localized strings. + * + * the default implementation returns the infos set via @p addTechnicalInfo + */ + virtual QStringList supportedTechnicalInfos() const; + + /** + * The framework will call this method with all strings returned by the + * supportedTechnicalInfos() method. It should return localized strings. + * + * the default implementation returns the infos set via @p addTechnicalInfo + */ + virtual QString technicalInfo( const QString& ) const; + + /** + * returnes -1 on error, 0 when finished, length of data otherwise + * takes care of padding + * calls decodeInternal() to actually decode data + * + * Fill the data buffer with maximal maxLen bytes. + */ + int decode( char* data, int maxLen ); + + /** + * Cleanup after decoding like closing files. + * Be aware that this is the counterpart to @p initDecoder(). + * + * There might happen multiple calls to initDecoder() and cleanup(). + */ + virtual void cleanup(); + + /** + * Seek to the position pos. + * Decoding is started new. That means that the data will be padded to + * length() - pos. + * returnes true on success; + */ + bool seek( const K3b::Msf& pos ); + + /** + * Be aware that one cannot rely + * on the file length until analyseFile() has been called. + */ + virtual K3b::Msf length() const { return m_length; } + + const QString& filename() const { return m_fileName; } + + // some helper methods + static void fromFloatTo16BitBeSigned( float* src, char* dest, int samples ); + static void from16bitBeSignedToFloat( char* src, float* dest, int samples ); + static void from8BitTo16BitBeSigned( char* src, char* dest, int samples ); + + protected: + /** + * Use this method if using the default implementation of @p metaInfo + */ + void addMetaInfo( MetaDataField, const QString& ); + + /** + * Use this method if using the default implementation of @p technicalInfo + * and @p supportedTechnicalInfos. + */ + void addTechnicalInfo( const QString&, const QString& ); + + /** + * This will be called once before the first call to decodeInternal. + * Use it to initialize decoding structures if necessary. + * + * There might happen multiple calls to initDecoder() and cleanup(). + */ + virtual bool initDecoderInternal() = 0; + + /** + * This method should analyze the file to determine the exact length, + * the samplerate in Hz, and the number of channels. The framework takes care of + * resampling and converting mono to stereo data. + * This method may be time consuming. + */ + virtual bool analyseFileInternal( K3b::Msf& length, int& samplerate, int& channels ) = 0; + + /** + * fill the already allocated data with maximal maxLen bytes of decoded samples. + * The framework will take care of padding or cutting the decoded data as well + * as resampling to 44100 Hz and converting mono samples to stereo. + */ + virtual int decodeInternal( char* data, int maxLen ) = 0; + + virtual bool seekInternal( const K3b::Msf& ) { return false; } + + private: + int resample( char* data, int maxLen ); + + QString m_fileName; + K3b::Msf m_length; + + class Private; + Private* d; +}; + + + +/** + * PluginFactory that needs to be subclassed in order to create an + * audio decoder. + * We need this because K3b uses multiple AudioDecoders of the same type at the + * same time. + */ +class LIBK3B_EXPORT K3bAudioDecoderFactory : public K3bPlugin +{ + Q_OBJECT + + public: + K3bAudioDecoderFactory( QObject* parent = 0, const char* name = 0 ) + : K3bPlugin( parent, name ) { + } + + virtual ~K3bAudioDecoderFactory() { + } + + QString group() const { return "AudioDecoder"; } + + /** + * K3b uses this flag to decide which plugins to test first + * when searching for an audio decoder. + * + * Decoders that are specialized on one format are favored over + * multi-format-decoders. + */ + virtual bool multiFormatDecoder() const { return false; } + + /** + * This is the most important method of the AudioDecoderFactory. + * It is used to determine if a certain file can be decoded by the + * decoder this factory creates. + * It is important that this method does not work lazy since it will + * be called with urls to every kind of files and if it returns true + * a decoder of this type is used for the file. + */ + virtual bool canDecode( const KURL& filename ) = 0; + + virtual K3bAudioDecoder* createDecoder( QObject* parent = 0, const char* name = 0 ) const = 0; + + /** + * Searching for an audiodecoder for @p filename. + * + * It first searches the single format decoder and the the multiformat decoder. + * + * @returns a newly created decoder on success and 0 when no decoder could be found. + */ + static K3bAudioDecoder* createDecoder( const KURL& url ); +}; + +#endif diff --git a/libk3b/plugin/k3baudioencoder.cpp b/libk3b/plugin/k3baudioencoder.cpp new file mode 100644 index 0000000..3b1309a --- /dev/null +++ b/libk3b/plugin/k3baudioencoder.cpp @@ -0,0 +1,175 @@ +/* + * + * $Id: k3baudioencoder.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudioencoder.h" + +#include + +#include + + +class K3bAudioEncoder::Private +{ +public: + Private() + : outputFile(0) { + } + + QFile* outputFile; + QString outputFilename; + + QString lastErrorString; +}; + + +K3bAudioEncoder::K3bAudioEncoder( QObject* parent, const char* name ) + : K3bPlugin( parent, name ) +{ + d = new Private(); +} + + +K3bAudioEncoder::~K3bAudioEncoder() +{ + closeFile(); + delete d; +} + + +bool K3bAudioEncoder::openFile( const QString& ext, const QString& filename, const K3b::Msf& length ) +{ + closeFile(); + + d->outputFile = new QFile( filename ); + if( d->outputFile->open( IO_WriteOnly ) ) { + return initEncoder( ext, length ); + } + else { + kdDebug() << "(K3bAudioEncoder) unable to open file " << filename << endl; + closeFile(); + return false; + } +} + + +bool K3bAudioEncoder::isOpen() const +{ + if( d->outputFile ) + return d->outputFile->isOpen(); + else + return false; +} + + +void K3bAudioEncoder::closeFile() +{ + if( d->outputFile ) { + finishEncoder(); + if( d->outputFile->isOpen() ) + d->outputFile->close(); + delete d->outputFile; + d->outputFile = 0; + d->outputFilename = QString::null; + } +} + + +const QString& K3bAudioEncoder::filename() const +{ + if( d->outputFile ) + return d->outputFilename; + else + return QString::null; +} + + + +void K3bAudioEncoder::setMetaData( K3bAudioEncoder::MetaDataField f, const QString& data ) +{ + if( !data.isEmpty() ) + return setMetaDataInternal( f, data ); +} + + +long K3bAudioEncoder::encode( const char* data, Q_ULONG len ) +{ + return encodeInternal( data, len ); +} + + +bool K3bAudioEncoder::initEncoder( const QString& ext, const K3b::Msf& length ) +{ + if( !isOpen() ) { + kdDebug() << "(K3bAudioEncoder) call to initEncoder without openFile!" << endl; + return false; + } + + return initEncoderInternal( ext, length ); +} + + +Q_LONG K3bAudioEncoder::writeData( const char* data, Q_ULONG len ) +{ + if( d->outputFile ) { + return d->outputFile->writeBlock( data, len ); + } + else { + kdDebug() << "(K3bAudioEncoder) call to writeData without opening a file first." << endl; + return -1; + } +} + + +bool K3bAudioEncoder::initEncoderInternal( const QString&, const K3b::Msf& ) +{ + // do nothing + return true; +} + + +void K3bAudioEncoder::setMetaDataInternal( K3bAudioEncoder::MetaDataField, const QString& ) +{ + // do nothing +} + + +void K3bAudioEncoder::finishEncoder() +{ + if( isOpen() ) + finishEncoderInternal(); +} + + +void K3bAudioEncoder::finishEncoderInternal() +{ + // do nothing +} + + +void K3bAudioEncoder::setLastError( const QString& e ) +{ + d->lastErrorString = e; +} + + +QString K3bAudioEncoder::lastErrorString() const +{ + if( d->lastErrorString.isEmpty() ) + return i18n("An unknown error occurred."); + else + return d->lastErrorString; +} + +#include "k3baudioencoder.moc" diff --git a/libk3b/plugin/k3baudioencoder.h b/libk3b/plugin/k3baudioencoder.h new file mode 100644 index 0000000..137b49d --- /dev/null +++ b/libk3b/plugin/k3baudioencoder.h @@ -0,0 +1,203 @@ +/* + * + * $Id: k3baudioencoder.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_ENCODER_H_ +#define _K3B_AUDIO_ENCODER_H_ + +#include + +#include +#include "k3b_export.h" + + +/** + * The base class for all audio encoders. + * Do not be alarmed by the number of methods since most of them + * do not need to be touched. They are just there to keep the API + * clean and extendable. + * + * see the skeleton files for further help. + */ +class LIBK3B_EXPORT K3bAudioEncoder : public K3bPlugin +{ + Q_OBJECT + + public: + K3bAudioEncoder( QObject* parent = 0, const char* name = 0 ); + virtual ~K3bAudioEncoder(); + + // TODO: if the following methods are to be activated the config methods in + // K3bPluginConfigWidget also need to be changed since they do not allow + // to use an extern config object yet. + // Perhaps these two methods should even go into K3bPlugin. + /** + * This calls readConfig using the k3bcore config object + */ + // void readConfig(); + + /** + * Force the plugin to read it's configuration + */ + // virtual void readConfig( KConfig* ); + + QString group() const { return "AudioEncoder"; } + + /** + * This should return the fileextensions supported by the filetype written in the + * encoder. + * May return an empty list in which case the encoder will not be usable (this may come + * in handy if the encoder is based on some external program or lib which is not + * available on runtime.) + */ + virtual QStringList extensions() const = 0; + + /** + * The filetype as presented to the user. + */ + virtual QString fileTypeComment( const QString& extension ) const = 0; + + /** + * Determine the filesize of the encoded file (~) + * default implementation returnes -1 (unknown) + * First parameter is the extension to be used + */ + virtual long long fileSize( const QString&, const K3b::Msf& ) const { return -1; } + + /** + * The default implementation openes the file for writing with + * writeData. Normally this does not need to be reimplemented. + * @param extension the filetype to be used. + * + */ + virtual bool openFile( const QString& extension, const QString& filename, const K3b::Msf& length ); + + + /** + * The default implementation returnes true if openFile (default implementation) has been + * successfully called. Normally this does not need to be reimplemented but it has to be + * if openFile is reimplemented. + */ + virtual bool isOpen() const; + + /** + * The default implementation closes the file opened by openFile + * (default implementation) + * Normally this does not need to be reimplemented but it has to be + * if openFile is reimplemented. + */ + virtual void closeFile(); + + /** + * The default implementation returnes the filename set in openFile + * or QString::null if no file has been opened. + * Normally this does not need to be reimplemented but it has to be + * if openFile is reimplemented. + */ + virtual const QString& filename() const; + + enum MetaDataField { + META_TRACK_TITLE, + META_TRACK_ARTIST, + META_TRACK_COMMENT, + META_TRACK_NUMBER, + META_ALBUM_TITLE, + META_ALBUM_ARTIST, + META_ALBUM_COMMENT, + META_YEAR, + META_GENRE }; + + /** + * Calling this method does only make sense after successfully + * calling openFile and before calling encode. + * This calls setMetaDataInternal. + */ + void setMetaData( MetaDataField, const QString& ); + + /** + * Returnes the amount of actually written bytes or -1 if an error + * occurred. + * + * Be aware that the returned amount of written data may very well differ + * from len since the data is encoded. + */ + long encode( const char*, Q_ULONG len ); + + /** + * Use this signal in case of an error to provide the user with information + * about the problem. + */ + virtual QString lastErrorString() const; + + protected: + /** + * Called by the default implementation of openFile + * This calls initEncoderInternal. + */ + bool initEncoder( const QString& extension, const K3b::Msf& length ); + + /** + * Called by the deafult implementation of openFile + * This calls finishEncoderInternal. + */ + void finishEncoder(); + + /** + * Use this to write the data to the file when + * using the default implementation of openFile + * Returnes the number of bytes actually written. + */ + Q_LONG writeData( const char*, Q_ULONG len ); + + /** + * initzialize the decoder structures. + * default implementation does nothing + * this may already write data. + */ + virtual bool initEncoderInternal( const QString& extension, const K3b::Msf& length ); + + /** + * reimplement this if the encoder needs to do some + * finishing touch. + */ + virtual void finishEncoderInternal(); + + /** + * encode the data and write it with writeData (when using + * the default) + * The data will always be 16bit 44100 Hz stereo little endian samples. + * Should return the amount of actually written bytes (may be 0) and -1 + * on error. + */ + // TODO: use Q_INT16* instead of char* + // FIXME: why little endian while CDs use big endian??? + virtual long encodeInternal( const char*, Q_ULONG len ) = 0; + + /** + * default implementation does nothing + * this may already write data. + */ + virtual void setMetaDataInternal( MetaDataField, const QString& ); + + /** + * Use this in combination with the default implementation of lastError() + */ + void setLastError( const QString& ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/plugin/k3baudiooutputplugin.h b/libk3b/plugin/k3baudiooutputplugin.h new file mode 100644 index 0000000..97e897a --- /dev/null +++ b/libk3b/plugin/k3baudiooutputplugin.h @@ -0,0 +1,69 @@ +/* + * + * $Id: k3baudiooutputplugin.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_OUTPUTPLUGIN_H_ +#define _K3B_AUDIO_OUTPUTPLUGIN_H_ + +#include +#include "k3b_export.h" + +/** + * + */ +class LIBK3B_EXPORT K3bAudioOutputPlugin : public K3bPlugin +{ + Q_OBJECT + + public: + virtual ~K3bAudioOutputPlugin() { + } + + QString group() const { return "AudioOutput"; } + + /** + * This is the short name of the sound system which can be used + * to specify the sound system on the command line (like "arts", "alsa", or "oss") + */ + virtual QCString soundSystem() const = 0; + + /** + * Initialize the plugin. + * + * Return true on success. + * In case of a failure report the error through lastErrorMessage + */ + virtual bool init() { return true; } + + /** + * Cleanup the plugin. This is the counterpart to init() + */ + virtual void cleanup() {} + + virtual QString lastErrorMessage() const { return QString::null; } + + /** + * Let there be sound... + * + * @returns number of written bytes or -1 on error. + */ + virtual int write( char* data, int len ) = 0; + + protected: + K3bAudioOutputPlugin( QObject* parent = 0, const char* name = 0 ) + : K3bPlugin( parent, name ) { + } +}; + +#endif diff --git a/libk3b/plugin/k3baudioserver.cpp b/libk3b/plugin/k3baudioserver.cpp new file mode 100644 index 0000000..ecfb25f --- /dev/null +++ b/libk3b/plugin/k3baudioserver.cpp @@ -0,0 +1,214 @@ +/* + * + * $Id: k3baudioserver.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include +#include +#include +#include "k3baudioserver.h" +#include "k3baudioclient.h" +#include "k3bpluginmanager.h" +#include "k3baudiooutputplugin.h" + +#include +#include +#include +#include + +#include + + + +K3bAudioServer* K3bAudioServer::s_instance = 0; + + + +class K3bAudioServer::Private : public K3bThread +{ +public: + Private( K3bAudioServer* s ) + : m_streaming(false), + m_server(s) { + setProgressInfoEventHandler( m_server ); + } + + + void stop() { + m_streaming = false; + } + +protected: + void run() { + m_streaming = true; + + char buffer[2048*10]; + + while( m_streaming ) { + int len = m_server->m_client->read( buffer, 2048*10 ); + if( len > 0 ) { + if( m_server->m_pluginInitialized ) { + if( write( buffer, len ) < 0 ) { + kdDebug() << "Audio Streaming failed: " << m_server->m_usedOutputPlugin->lastErrorMessage() << endl; + emitInfoMessage( m_server->m_usedOutputPlugin->lastErrorMessage(), 0 ); + return; + } + } + // else just drop the data into space... + } + else { + // FIXME: no data or error... what to do? + } + } + } + + int write( char* buffer, int len ) { + int written = m_server->m_usedOutputPlugin->write( buffer, len ); + return written; +// if( written < 0 ) +// return -1; +// else if( written < len ) +// return write( buffer+written, len-written ) + written; +// else +// return len; + } + +private: + bool m_streaming; + K3bAudioServer* m_server; +}; + + +K3bAudioServer::K3bAudioServer( QObject* parent, const char* name ) + : QObject( parent, name ), + m_usedOutputPlugin(0), + m_pluginInitialized(false), + m_client(0) +{ + s_instance = this; + d = new Private( this ); +} + + +K3bAudioServer::~K3bAudioServer() +{ + delete d; + s_instance = 0; +} + + +bool K3bAudioServer::setOutputMethod( const QCString& name ) +{ + if( K3bAudioOutputPlugin* p = findOutputPlugin( name ) ) { + setOutputPlugin( p ); + return true; + } + else + return false; +} + + +void K3bAudioServer::setOutputPlugin( K3bAudioOutputPlugin* p ) +{ + if( p != m_usedOutputPlugin ) { + bool restart = d->running(); + if( restart ) { + d->stop(); + d->wait(); + } + + if( m_usedOutputPlugin ) { + m_usedOutputPlugin->cleanup(); + m_pluginInitialized = false; + } + + m_usedOutputPlugin = p; + + if( restart ) + d->start(); + } +} + + +void K3bAudioServer::attachClient( K3bAudioClient* c ) +{ + // for now we simply allow only one client and stop the old one + if( m_client ) { + kdDebug() << "(K3bAudioServer) leaving old client hanging. :(" << endl; + detachClient( m_client ); + } + + m_client = c; + + if( m_usedOutputPlugin && !m_pluginInitialized ) { + if( !m_usedOutputPlugin->init() ) { + emit error( i18n("Could not initialize Audio Output plugin %1 (%2)") + .arg(m_usedOutputPlugin->pluginInfo().name()) + .arg(m_usedOutputPlugin->lastErrorMessage()) ); + } + else + m_pluginInitialized = true; + } + else + kdDebug() << "(K3bAudioServer::attachClient) no output plugin selected. Using null output." << endl; + + // start the streaming + d->start(); +} + + +void K3bAudioServer::detachClient( K3bAudioClient* c ) +{ + if( m_client == c ) { + m_client = 0; + + // stop the streaming + d->stop(); + d->wait(); + + if( m_usedOutputPlugin && m_pluginInitialized ) { + m_usedOutputPlugin->cleanup(); + m_pluginInitialized = false; + } + } +} + + +K3bAudioOutputPlugin* K3bAudioServer::findOutputPlugin( const QCString& name ) +{ + QPtrList fl = k3bcore->pluginManager()->plugins( "AudioOutput" ); + + for( QPtrListIterator it( fl ); it.current(); ++it ) { + K3bAudioOutputPlugin* f = dynamic_cast( it.current() ); + + if( f && f->soundSystem() == name ) { + return f; + } + } + + kdDebug() << "(K3bAudioServer::findOutputPlugin) could not find output plugin " << name << endl; + + return 0; +} + + +void K3bAudioServer::customEvent( QCustomEvent* e ) +{ + if( K3bProgressInfoEvent* be = dynamic_cast(e) ) { + if( be->type() == K3bProgressInfoEvent::InfoMessage ) { + emit error( be->firstString() ); + } + } +} + +#include "k3baudioserver.moc" diff --git a/libk3b/plugin/k3baudioserver.h b/libk3b/plugin/k3baudioserver.h new file mode 100644 index 0000000..1e8d4a8 --- /dev/null +++ b/libk3b/plugin/k3baudioserver.h @@ -0,0 +1,85 @@ +/* + * + * $Id$ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_SERVER_H_ +#define _K3B_AUDIO_SERVER_H_ + +#include +#include "k3b_export.h" +class K3bAudioOutputPlugin; +class K3bAudioClient; + + +/** + * The AudioServer manages AudioClients to play audio data through + * some output plugin. + */ +class LIBK3B_EXPORT K3bAudioServer : public QObject +{ + Q_OBJECT + + public: + K3bAudioServer( QObject* parent = 0, const char* name = 0 ); + ~K3bAudioServer(); + + /** + * Returns false in case the named output method could not be found. + */ + bool setOutputMethod( const QCString& name ); + void setOutputPlugin( K3bAudioOutputPlugin* p ); + + /** + * Start playing the clients data. It's up to the server if older + * clients are suspended, stopped or mixed into a single stream. + * + * This is called by K3bAudioClient + */ + void attachClient( K3bAudioClient* ); + + /** + * Stop streaming data from the client. + * This is called by K3bAudioClient + */ + void detachClient( K3bAudioClient* ); + + /** + * We need to be able to play data from everywhere in K3b. + */ + static K3bAudioServer* instance() { return s_instance; } + + /** + * Find a plugin by classname. + */ + static K3bAudioOutputPlugin* findOutputPlugin( const QCString& name ); + + signals: + void error( const QString& ); + + private: + void customEvent( QCustomEvent* e ); + + class Private; + friend class Private; + + static K3bAudioServer* s_instance; + + K3bAudioOutputPlugin* m_usedOutputPlugin; + bool m_pluginInitialized; + K3bAudioClient* m_client; + + Private* d; +}; + +#endif diff --git a/libk3b/plugin/k3bplugin.cpp b/libk3b/plugin/k3bplugin.cpp new file mode 100644 index 0000000..db75bb4 --- /dev/null +++ b/libk3b/plugin/k3bplugin.cpp @@ -0,0 +1,36 @@ +/* + * + * $Id: k3bplugin.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bplugin.h" + + +K3bPlugin::K3bPlugin( QObject* parent, const char* name ) + : QObject( parent, name ) +{ +} + + +K3bPlugin::~K3bPlugin() +{ +} + + +K3bPluginConfigWidget* K3bPlugin::createConfigWidget( QWidget*, const char* ) const +{ + return 0; +} + +#include "k3bplugin.moc" diff --git a/libk3b/plugin/k3bplugin.h b/libk3b/plugin/k3bplugin.h new file mode 100644 index 0000000..f4501a7 --- /dev/null +++ b/libk3b/plugin/k3bplugin.h @@ -0,0 +1,113 @@ +/* + * + * $Id: k3bplugin.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_PLUGIN_H_ +#define _K3B_PLUGIN_H_ + +#include +#include +#include "k3b_export.h" + +#define K3B_PLUGIN_SYSTEM_VERSION 3 + + +class K3bPluginConfigWidget; +class QWidget; + + + +class K3bPluginInfo +{ + friend class K3bPluginManager; + + public: + K3bPluginInfo() { + } + + K3bPluginInfo( QString libraryName, + QString name, + QString author, + QString email, + QString comment, + QString version, + QString licence ) + : m_libraryName(libraryName), + m_name(name), + m_author(author), + m_email(email), + m_comment(comment), + m_version(version), + m_licence(licence) { + } + + const QString& name() const { return m_name; } + const QString& author() const { return m_author; } + const QString& email() const { return m_email; } + const QString& comment() const { return m_comment; } + const QString& version() const { return m_version; } + const QString& licence() const { return m_licence; } + + const QString& libraryName() const { return m_libraryName; } + + private: + QString m_libraryName; + + QString m_name; + QString m_author; + QString m_email; + QString m_comment; + QString m_version; + QString m_licence; +}; + + +/** + * Base class for all plugins. You may use the K3bPluginFactory to make your plugin available. + */ +class LIBK3B_EXPORT K3bPlugin : public QObject +{ + Q_OBJECT + + friend class K3bPluginManager; + + public: + K3bPlugin( QObject* parent = 0, const char* name = 0 ); + virtual ~K3bPlugin(); + + const K3bPluginInfo& pluginInfo() const { return m_pluginInfo; } + + /** + * Version of the plugin system this plugin was written for. + */ + virtual int pluginSystemVersion() const = 0; + + /** + * The plugin group. + */ + virtual QString group() const = 0; + + /** + * Returns a widget which configures the plugin. + * + * The caller has to destroy the widget + */ + virtual K3bPluginConfigWidget* createConfigWidget( QWidget* parent = 0, const char* name = 0 ) const; + + private: + K3bPluginInfo m_pluginInfo; +}; + +#endif diff --git a/libk3b/plugin/k3bpluginconfigwidget.cpp b/libk3b/plugin/k3bpluginconfigwidget.cpp new file mode 100644 index 0000000..09b7f0b --- /dev/null +++ b/libk3b/plugin/k3bpluginconfigwidget.cpp @@ -0,0 +1,48 @@ +/* + * + * $Id: k3bpluginconfigwidget.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bpluginconfigwidget.h" +#include "k3bpluginfactory.h" + +#include + +#include +#include + + +K3bPluginConfigWidget::K3bPluginConfigWidget( QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ +} + + +K3bPluginConfigWidget::~K3bPluginConfigWidget() +{ +} + + +void K3bPluginConfigWidget::loadConfig() +{ + // do nothing +} + + +void K3bPluginConfigWidget::saveConfig() +{ + // do nothing +} + + +#include "k3bpluginconfigwidget.moc" diff --git a/libk3b/plugin/k3bpluginconfigwidget.h b/libk3b/plugin/k3bpluginconfigwidget.h new file mode 100644 index 0000000..baa07ab --- /dev/null +++ b/libk3b/plugin/k3bpluginconfigwidget.h @@ -0,0 +1,40 @@ +/* + * + * $Id: k3bpluginconfigwidget.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_PLUGIN_CONFIG_WIDGET_H_ +#define _K3B_PLUGIN_CONFIG_WIDGET_H_ + +#include +#include "k3b_export.h" + +class LIBK3B_EXPORT K3bPluginConfigWidget : public QWidget +{ + Q_OBJECT + + public: + K3bPluginConfigWidget( QWidget* parent = 0, const char* name = 0 ); + virtual ~K3bPluginConfigWidget(); + + public slots: + /** + * Use k3bcore->config() to store the settings + * FIXME: add a KConfig parameter here + */ + virtual void loadConfig(); + virtual void saveConfig(); +}; + +#endif diff --git a/libk3b/plugin/k3bpluginfactory.cpp b/libk3b/plugin/k3bpluginfactory.cpp new file mode 100644 index 0000000..7d8f8fe --- /dev/null +++ b/libk3b/plugin/k3bpluginfactory.cpp @@ -0,0 +1,33 @@ +/* + * + * $Id: k3bpluginfactory.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bpluginfactory.h" + + +template +KInstance* K3bPluginFactory::s_instance = 0; + + +template +K3bPluginFactory* K3bPluginFactory::s_self = 0; + + +template +KInstance* K3bPluginFactory::instance() +{ + if( !s_instance && s_self ) + s_instance = new KInstance( s_self->m_instanceName ); + return s_instance; +} diff --git a/libk3b/plugin/k3bpluginfactory.h b/libk3b/plugin/k3bpluginfactory.h new file mode 100644 index 0000000..6dbc6cb --- /dev/null +++ b/libk3b/plugin/k3bpluginfactory.h @@ -0,0 +1,98 @@ +/* + * + * $Id: k3bpluginfactory.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_PLUGIN_FACTORY_H_ +#define _K3B_PLUGIN_FACTORY_H_ + +#include +#include +#include +#include + +/** + * Template based on KGenericFactory. This is just here to avoid using the QStringList args parameter + * in every plugin's constructor. + * + * Use this as follows: + * K_EXPORT_COMPONENT_FACTORY( libk3bartsaudioserver, K3bPluginFactory( "k3bartsaudioserver" ) ) + * + * See KGenericFactory for more information. + */ +template +class K3bPluginFactory : public KLibFactory +{ + public: + K3bPluginFactory( const char* instanceName ) + : m_instanceName(instanceName) { + s_self = this; + m_catalogueInitialized = false; + } + + ~K3bPluginFactory() { + if ( s_instance ) + KGlobal::locale()->removeCatalogue( s_instance->instanceName() ); + delete s_instance; + s_instance = 0; + s_self = 0; + } + + static KInstance* instance(); + + protected: + virtual void setupTranslations( void ) { + if( instance() ) + KGlobal::locale()->insertCatalogue( instance()->instanceName() ); + } + + void initializeMessageCatalogue() { + if( !m_catalogueInitialized ) { + m_catalogueInitialized = true; + setupTranslations(); + } + } + + virtual QObject* createObject( QObject *parent, const char *name, + const char*, const QStringList& ) { + initializeMessageCatalogue(); + return new T( parent, name ); + } + + private: + QCString m_instanceName; + bool m_catalogueInitialized; + + static KInstance* s_instance; + static K3bPluginFactory *s_self; +}; + + +template +KInstance* K3bPluginFactory::s_instance = 0; + + +template +K3bPluginFactory* K3bPluginFactory::s_self = 0; + + +template +KInstance* K3bPluginFactory::instance() +{ + if( !s_instance && s_self ) + s_instance = new KInstance( s_self->m_instanceName ); + return s_instance; +} + +#endif diff --git a/libk3b/plugin/k3bpluginmanager.cpp b/libk3b/plugin/k3bpluginmanager.cpp new file mode 100644 index 0000000..3e963a2 --- /dev/null +++ b/libk3b/plugin/k3bpluginmanager.cpp @@ -0,0 +1,189 @@ +/* + * + * $Id: k3bpluginmanager.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bpluginmanager.h" +#include "k3bplugin.h" +#include "k3bpluginconfigwidget.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + + +class K3bPluginManager::Private +{ +public: + QPtrList plugins; +}; + + + + +K3bPluginManager::K3bPluginManager( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + d = new Private(); +} + + +K3bPluginManager::~K3bPluginManager() +{ + delete d; +} + + + +QStringList K3bPluginManager::groups() const +{ + QStringList grps; + + QPtrList fl; + for( QPtrListIterator it( d->plugins ); + it.current(); ++it ) { + if( !grps.contains( it.current()->group() ) ) + grps.append( it.current()->group() ); + } + + return grps; +} + + +QPtrList K3bPluginManager::plugins( const QString& group ) const +{ + QPtrList fl; + for( QPtrListIterator it( d->plugins ); + it.current(); ++it ) { + if( it.current()->group() == group || group.isEmpty() ) + fl.append( it.current() ); + } + return fl; +} + + +void K3bPluginManager::loadPlugin( const QString& fileName ) +{ + KSimpleConfig c( fileName, true ); + c.setGroup( "K3b Plugin" ); + + QString libName = c.readEntry( "Lib" ); + if( libName.isEmpty() ) { + kdDebug() << "(K3bPluginManager) no Lib specified in " << fileName << endl; + return; + } + + // read the lib + KLibFactory* factory = KLibLoader::self()->factory( libName.latin1() ); + if( factory ) { + K3bPlugin* plugin = dynamic_cast( factory->create( this ) ); + if( plugin ) { + // FIXME: improve this versioning stuff + if( plugin->pluginSystemVersion() != K3B_PLUGIN_SYSTEM_VERSION ) { + delete plugin; + kdDebug() << "(K3bPluginManager) plugin system does not fit lib " << libName << endl; + } + else { + plugin->m_pluginInfo = K3bPluginInfo( libName, + c.readEntry( "Name" ), + c.readEntry( "Author" ), + c.readEntry( "Email" ), + c.readEntry( "Comment" ), + c.readEntry( "Version" ), + c.readEntry( "License" ) ); + + // make sure to only use the latest version of one plugin + bool addPlugin = true; + for( QPtrListIterator it( d->plugins ); *it; ++it ) { + if( it.current()->pluginInfo().name() == plugin->pluginInfo().name() ) { + if( K3bVersion(it.current()->pluginInfo().version()) < K3bVersion(plugin->pluginInfo().version()) ) { + K3bPlugin* p = it.current(); + d->plugins.removeRef( p ); + delete p; + } + else { + addPlugin = false; + } + break; + } + } + if( addPlugin ) + d->plugins.append( plugin ); + else + delete plugin; + } + } + else + kdDebug() << "(K3bPluginManager) lib " << libName << " not a K3b plugin" << endl; + } + else + kdDebug() << "(K3bPluginManager) lib " << libName << " not found" << endl; +} + + +void K3bPluginManager::loadAll() +{ + // we simply search the K3b plugin dir for now + QStringList dirs = KGlobal::dirs()->findDirs( "data", "k3b/plugins/" ); + + for( QStringList::const_iterator it = dirs.begin(); + it != dirs.end(); ++it ) { + QStringList entries = QDir(*it).entryList( "*.plugin", QDir::Files ); + for( QStringList::const_iterator it2 = entries.begin(); + it2 != entries.end(); ++it2 ) { + loadPlugin( *it + *it2 ); + } + } +} + +int K3bPluginManager::pluginSystemVersion() const +{ + return K3B_PLUGIN_SYSTEM_VERSION; +} + + +int K3bPluginManager::execPluginDialog( K3bPlugin* plugin, QWidget* parent, const char* name ) +{ + KDialogBase dlg( parent, + name, + true, + i18n("Configure plugin %1").arg( plugin->pluginInfo().name() ) ); + + K3bPluginConfigWidget* configWidget = plugin->createConfigWidget( &dlg ); + if( configWidget ) { + dlg.setMainWidget( configWidget ); + connect( &dlg, SIGNAL(applyClicked()), configWidget, SLOT(saveConfig()) ); + connect( &dlg, SIGNAL(okClicked()), configWidget, SLOT(saveConfig()) ); + configWidget->loadConfig(); + int r = dlg.exec(); + delete configWidget; + return r; + } + else { + KMessageBox::sorry( parent, i18n("No settings available for plugin %1.").arg( plugin->pluginInfo().name() ) ); + return 0; + } +} + +#include "k3bpluginmanager.moc" diff --git a/libk3b/plugin/k3bpluginmanager.h b/libk3b/plugin/k3bpluginmanager.h new file mode 100644 index 0000000..9295dee --- /dev/null +++ b/libk3b/plugin/k3bpluginmanager.h @@ -0,0 +1,70 @@ +/* + * + * $Id: k3bpluginmanager.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_PLUGIN_MANAGER_H_ +#define _K3B_PLUGIN_MANAGER_H_ + +#include +#include +#include +#include "k3b_export.h" + + +class K3bPlugin; +class QWidget; + + +/** + * Use this class to access all K3b plugins (this does not include the + * KParts Plugins!). + * Like the K3bCore the single instance (which has to be created manually) + * can be obtained with the k3bpluginmanager macro. + */ +class LIBK3B_EXPORT K3bPluginManager : public QObject +{ + Q_OBJECT + + public: + K3bPluginManager( QObject* parent = 0, const char* name = 0 ); + ~K3bPluginManager(); + + /** + * if group is empty all plugins are returned + */ + QPtrList plugins( const QString& group = QString::null ) const; + + /** + * Returnes a list of the available groups. + */ + QStringList groups() const; + + int pluginSystemVersion() const; + + public slots: + /** + * Loads all plugins from the ressource directories. + */ + void loadAll(); + + void loadPlugin( const QString& fileName ); + + int execPluginDialog( K3bPlugin*, QWidget* parent = 0, const char* name = 0 ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/plugin/k3bprojectplugin.h b/libk3b/plugin/k3bprojectplugin.h new file mode 100644 index 0000000..c15b9a3 --- /dev/null +++ b/libk3b/plugin/k3bprojectplugin.h @@ -0,0 +1,161 @@ +/* + * + * $Id: k3bprojectplugin.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_PROJECT_PLUGIN_H_ +#define _K3B_PROJECT_PLUGIN_H_ + +#include +#include +#include "k3b_export.h" +class K3bDoc; + +/** + * In case your plugin provides a GUI it is recommended to use the + * K3bProjectPluginGUIBase interface. That way K3b can embed the GUI into + * a fancy dialog which fits the overall look. + * + * This is not derived from QWidget to make it possible to inherit + * from other QWidget derivates. + */ +class K3bProjectPluginGUIBase +{ + public: + K3bProjectPluginGUIBase() {} + virtual ~K3bProjectPluginGUIBase() {} + + virtual QWidget* qWidget() = 0; + + /** + * Title used for the GUI + */ + virtual QString title() const = 0; + virtual QString subTitle() const { return QString::null; } + + virtual void readSettings( KConfigBase* ) {} + virtual void saveSettings( KConfigBase* ) {} + + /** + * Load system defaults for the GUI + */ + virtual void loadDefaults() {} + + /** + * Start the plugin. This method should do the actual work. + */ + virtual void activate() = 0; +}; + + +/** + * A K3bProjectPlugin is supposed to modify a k3b project in some way or + * create additional data based on the project. + * + * Reimplement createGUI or activate and use setText, setToolTip, setWhatsThis, and setIcon + * to specify the gui elements used when presenting the plugin to the user. + */ +class LIBK3B_EXPORT K3bProjectPlugin : public K3bPlugin +{ + Q_OBJECT + + public: + /** + * @param type The type of the plugin + * @param gui If true the plugin is supposed to provide a widget via @p createGUI(). In that case + * @p activate() will not be used. A plugin has a GUI if it's functionality is started + * by some user input. + */ + K3bProjectPlugin( int type, bool gui = false, QObject* parent = 0, const char* name = 0 ) + : K3bPlugin( parent, name ), + m_type(type), + m_hasGUI(gui) { + } + + virtual ~K3bProjectPlugin() { + } + + // TODO: move this to K3bDoc? + enum Type { + AUDIO_CD = 0x1, + DATA_CD = 0x2, + MIXED_CD = 0x4, + VIDEO_CD = 0x8, + MOVIX_CD = 0x10, + DATA_DVD = 0x20, + VIDEO_DVD = 0x40, + MOVIX_DVD = 0x80, + DATA_PROJECTS = DATA_CD|DATA_DVD, + MOVIX_PROJECTS = MOVIX_CD|MOVIX_DVD + }; + + // TODO: maybe we should use something like "ProjectPlugin/AudioCD" based on the type? + QString group() const { return "ProjectPlugin"; } + + /** + * audio, data, videocd, or videodvd + * Needs to return a proper type. The default implementation returns the type specified + * in the constructor. + */ + virtual int type() const { return m_type; } + + /** + * Text used for menu entries and the like. + */ + const QString& text() const { return m_text; } + const QString& toolTip() const { return m_toolTip; } + const QString& whatsThis() const { return m_whatsThis; } + const QString& icon() const { return m_icon; } + + bool hasGUI() const { return m_hasGUI; } + + /** + * Create the GUI which provides the features for the plugin. + * This only needs to be implemented in case hasGUI returns true. + * The returned object has to be a QWidget based class. + * + * @param doc based on the type returned by the factory + * this will be the doc to work on. It should + * be dynamically casted to the needed project type. + */ + virtual K3bProjectPluginGUIBase* createGUI( K3bDoc* doc, QWidget* = 0, const char* = 0 ) { Q_UNUSED(doc); return 0; } + + /** + * This is where the action happens. + * There is no need to implement this in case hasGUI returns true. + * + * @param doc based on the type returned by the factory + * this will be the doc to work on. It should + * be dynamically casted to the needed project type. + * + * @param parent the parent widget to be used for things like progress dialogs. + */ + virtual void activate( K3bDoc* doc, QWidget* parent ) { Q_UNUSED(doc); Q_UNUSED(parent); } + + protected: + void setText( const QString& s ) { m_text = s; } + void setToolTip( const QString& s ) { m_toolTip = s; } + void setWhatsThis( const QString& s ) { m_whatsThis = s; } + void setIcon( const QString& s ) { m_icon = s; } + + private: + int m_type; + bool m_hasGUI; + QString m_text; + QString m_toolTip; + QString m_whatsThis; + QString m_icon; +}; + + +#endif diff --git a/libk3b/plugin/libsamplerate/Makefile.am b/libk3b/plugin/libsamplerate/Makefile.am new file mode 100644 index 0000000..3154ce2 --- /dev/null +++ b/libk3b/plugin/libsamplerate/Makefile.am @@ -0,0 +1,20 @@ +# This file was automatically generated from the Makefile.am +# DO NOT EDIT! + +noinst_LTLIBRARIES = libsamplerate.la +#include_HEADERS = samplerate.h + +EXTRA_DIST = config.h.in Version_script.in + +COEFF_HDRS = high_qual_coeffs.h mid_qual_coeffs.h fastest_coeffs.h + +noinst_HEADERS = common.h float_cast.h $(COEFF_HDRS) + +SRC_SOURCES = samplerate.c src_sinc.c src_zoh.c src_linear.c + +libsamplerate_la_SOURCES = $(SRC_SOURCES) +#libsamplerate_la_LDFLAGS = -version-info @SHARED_VERSION_INFO@ @SHLIB_VERSION_ARG@ +libsamplerate_la_LIBADD = -lm + +# Disable autoheader. +#AUTOHEADER=echo diff --git a/libk3b/plugin/libsamplerate/common.h b/libk3b/plugin/libsamplerate/common.h new file mode 100644 index 0000000..86021ae --- /dev/null +++ b/libk3b/plugin/libsamplerate/common.h @@ -0,0 +1,105 @@ +/* +** Copyright (C) 2002,2003 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef COMMON_H_INCLUDED +#define COMMON_H_INCLUDED + +#ifdef HAVE_STDINT_H +#include +#elif (SIZEOF_INT == 4) +typedef int int32_t ; +#elif (SIZEOF_LONG == 4) +typedef long int32_t ; +#endif + +#define SRC_MAX_RATIO 12 +#define SRC_MIN_RATIO_DIFF (1e-20) + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +#define MAKE_MAGIC(a,b,c,d,e,f) ((a)+((b)<<4)+((c)<<8)+((d)<<12)+((e)<<16)+((f)<<20)) + +#include "samplerate.h" + +enum +{ SRC_FALSE = 0, + SRC_TRUE = 1 +} ; + +enum +{ SRC_ERR_NO_ERROR = 0, + + SRC_ERR_MALLOC_FAILED, + SRC_ERR_BAD_STATE, + SRC_ERR_BAD_DATA, + SRC_ERR_BAD_DATA_PTR, + SRC_ERR_NO_PRIVATE, + SRC_ERR_BAD_SRC_RATIO, + SRC_ERR_BAD_PROC_PTR, + SRC_ERR_SHIFT_BITS, + SRC_ERR_FILTER_LEN, + SRC_ERR_BAD_CONVERTER, + SRC_ERR_BAD_CHANNEL_COUNT, + SRC_ERR_SINC_BAD_BUFFER_LEN, + SRC_ERR_SIZE_INCOMPATIBILITY, + SRC_ERR_BAD_PRIV_PTR, + SRC_ERR_BAD_SINC_STATE, + SRC_ERR_DATA_OVERLAP, + + /* This must be the last error number. */ + SRC_ERR_MAX_ERROR +} ; + +typedef struct SRC_PRIVATE_tag +{ double last_ratio, last_position ; + + void *private_data ; + + int (*process) (struct SRC_PRIVATE_tag *psrc, SRC_DATA *data) ; + void (*reset) (struct SRC_PRIVATE_tag *psrc) ; + + int error ; + int channels ; +} SRC_PRIVATE ; + +/* In src_sinc.c */ +int sinc_process (SRC_PRIVATE *psrc, SRC_DATA *data) ; + +const char* sinc_get_name (int src_enum) ; +const char* sinc_get_description (int src_enum) ; + +int sinc_set_converter (SRC_PRIVATE *psrc, int src_enum) ; + +/* In src_linear.c */ +int linear_process (SRC_PRIVATE *psrc, SRC_DATA *data) ; + +const char* linear_get_name (int src_enum) ; +const char* linear_get_description (int src_enum) ; + +int linear_set_converter (SRC_PRIVATE *psrc, int src_enum) ; + +/* In src_zoh.c */ +int zoh_process (SRC_PRIVATE *psrc, SRC_DATA *data) ; + +const char* zoh_get_name (int src_enum) ; +const char* zoh_get_description (int src_enum) ; + +int zoh_set_converter (SRC_PRIVATE *psrc, int src_enum) ; + +#endif /* COMMON_H_INCLUDED */ diff --git a/libk3b/plugin/libsamplerate/configure.in.in b/libk3b/plugin/libsamplerate/configure.in.in new file mode 100644 index 0000000..06a8f55 --- /dev/null +++ b/libk3b/plugin/libsamplerate/configure.in.in @@ -0,0 +1,13 @@ +LIBS="-lm $all_libraries" + +AC_CHECK_DECL(lrint, + AC_DEFINE(HAVE_LRINT,1,[Define if lrint is supported]), + AC_DEFINE(HAVE_LRINT,0,[Define if lrint is not supported]), + [#include ] +) + +AC_CHECK_DECL(lrintf, + AC_DEFINE(HAVE_LRINTF,1,[Define if lrintf is supported]), + AC_DEFINE(HAVE_LRINTF,0,[Define if lrintf is not supported]), + [#include ] +) diff --git a/libk3b/plugin/libsamplerate/fastest_coeffs.h b/libk3b/plugin/libsamplerate/fastest_coeffs.h new file mode 100644 index 0000000..5343fc6 --- /dev/null +++ b/libk3b/plugin/libsamplerate/fastest_coeffs.h @@ -0,0 +1,2493 @@ +/* +** Copyright (C) 2002,2003 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +/* +** f = make_filter (8, 128, 100.3) ; +** Pass band width : 0.0039062 (should be 0.0039062) +** Stop band atten. : 100.71 dB +** -3dB band width : 0.484 +** half length : 2463 +** increment : 128 +*/ + + 8.31472372954840555082e-01, + 8.31414005540308198583e-01, + 8.31238918266223869580e-01, + 8.30947156036480505392e-01, + 8.30538793675450581766e-01, + 8.30013935904800659316e-01, + 8.29372717311066987023e-01, + 8.28615302303967515840e-01, + 8.27741885065490623496e-01, + 8.26752689489751890761e-01, + 8.25647969113678215081e-01, + 8.24428007038499943704e-01, + 8.23093115842108757896e-01, + 8.21643637482293187624e-01, + 8.20079943190897053817e-01, + 8.18402433358933589780e-01, + 8.16611537412689103554e-01, + 8.14707713680854150873e-01, + 8.12691449252757824873e-01, + 8.10563259827706050764e-01, + 8.08323689555523805517e-01, + 8.05973310868314363198e-01, + 8.03512724303517833491e-01, + 8.00942558318331943035e-01, + 7.98263469095534694553e-01, + 7.95476140340800830231e-01, + 7.92581283071560838138e-01, + 7.89579635397499868255e-01, + 7.86471962292734527722e-01, + 7.83259055359786127148e-01, + 7.79941732585400893107e-01, + 7.76520838088307852054e-01, + 7.72997241859018080490e-01, + 7.69371839491718167992e-01, + 7.65645551908390675777e-01, + 7.61819325075220210586e-01, + 7.57894129711408459649e-01, + 7.53870960990470018181e-01, + 7.49750838234153449413e-01, + 7.45534804599028211314e-01, + 7.41223926755909090502e-01, + 7.36819294562192195208e-01, + 7.32322020727209643809e-01, + 7.27733240470738174110e-01, + 7.23054111174766811487e-01, + 7.18285812028632841830e-01, + 7.13429543667664534112e-01, + 7.08486527805442301009e-01, + 7.03458006859804640953e-01, + 6.98345243572719653891e-01, + 6.93149520624175785599e-01, + 6.87872140240182283755e-01, + 6.82514423795047564525e-01, + 6.77077711408058502407e-01, + 6.71563361534684655219e-01, + 6.65972750552474845875e-01, + 6.60307272341742135247e-01, + 6.54568337861228477514e-01, + 6.48757374718860524432e-01, + 6.42875826737744904271e-01, + 6.36925153517562181449e-01, + 6.30906829991492501541e-01, + 6.24822345978837789815e-01, + 6.18673205733470954470e-01, + 6.12460927488293727095e-01, + 6.06187042995817604307e-01, + 5.99853097065060292259e-01, + 5.93460647094893878339e-01, + 5.87011262603992944875e-01, + 5.80506524757569142281e-01, + 5.73948025891025337408e-01, + 5.67337369030688098981e-01, + 5.60676167411809700525e-01, + 5.53966043993961543279e-01, + 5.47208630974010734604e-01, + 5.40405569296826038261e-01, + 5.33558508163880174102e-01, + 5.26669104539922661168e-01, + 5.19739022657876970079e-01, + 5.12769933522119303326e-01, + 5.05763514410336290084e-01, + 4.98721448374081555155e-01, + 4.91645423738241937883e-01, + 4.84537133599546865348e-01, + 4.77398275324308896117e-01, + 4.70230550045545592219e-01, + 4.63035662159660077464e-01, + 4.55815318822846149427e-01, + 4.48571229447379538069e-01, + 4.41305105197960123586e-01, + 4.34018658488283970431e-01, + 4.26713602477997000495e-01, + 4.19391650570203500248e-01, + 4.12054515909689722530e-01, + 4.04703910882034223473e-01, + 3.97341546613763640927e-01, + 3.89969132473721613596e-01, + 3.82588375575806771689e-01, + 3.75200980283257823356e-01, + 3.67808647714624070701e-01, + 3.60413075251609871241e-01, + 3.53015956048925771960e-01, + 3.45618978546330835044e-01, + 3.38223825983006376461e-01, + 3.30832175914426429575e-01, + 3.23445699731881031180e-01, + 3.16066062184803764357e-01, + 3.08694920906066150312e-01, + 3.01333925940378832831e-01, + 2.93984719275965256102e-01, + 2.86648934379644393378e-01, + 2.79328195735489559492e-01, + 2.72024118387182545220e-01, + 2.64738307484245039003e-01, + 2.57472357832259801658e-01, + 2.50227853447243409057e-01, + 2.43006367114305704691e-01, + 2.35809459950733935063e-01, + 2.28638680973647728800e-01, + 2.21495566672345989279e-01, + 2.14381640585498134399e-01, + 2.07298412883298144305e-01, + 2.00247379954717363848e-01, + 1.93230023999986955108e-01, + 1.86247812628430653437e-01, + 1.79302198461779749294e-01, + 1.72394618743085786816e-01, + 1.65526494951356295537e-01, + 1.58699232422028796430e-01, + 1.51914219973401071195e-01, + 1.45172829539132269838e-01, + 1.38476415806921215879e-01, + 1.31826315863480453272e-01, + 1.25223848845901208904e-01, + 1.18670315599523901184e-01, + 1.12166998342411894374e-01, + 1.05715160336527447260e-01, + 9.93160455657086521652e-02, + 9.29708784205405536216e-02, + 8.66808633902153846673e-02, + 8.04471847614677826321e-02, + 7.42710063246745516574e-02, + 6.81534710872001986415e-02, + 6.20957009940759641076e-02, + 5.60987966560835549235e-02, + 5.01638370853247708703e-02, + 4.42918794383505357026e-02, + 3.84839587669171534490e-02, + 3.27410877764400740086e-02, + 2.70642565922108620236e-02, + 2.14544325334371267788e-02, + 1.59125598951669576520e-02, + 1.04395597381551803740e-02, + 5.03632968672305773861e-03, +-2.96256265336385191805e-04, +-5.55734794075828358179e-03, +-1.07461191566687631893e-02, +-1.58617678942645466689e-02, +-2.09035164602743607498e-02, +-2.58706116401622790435e-02, +-3.07623248430414844568e-02, +-3.55779522382659724178e-02, +-4.03168148836769782428e-02, +-4.49782588454727128013e-02, +-4.95616553096875425699e-02, +-5.40664006852556791594e-02, +-5.84919166986474642345e-02, +-6.28376504800633867154e-02, +-6.71030746411782619276e-02, +-7.12876873444269476554e-02, +-7.53910123638282386738e-02, +-7.94125991373483691715e-02, +-8.33520228108008270906e-02, +-8.72088842732959695914e-02, +-9.09828101842390379872e-02, +-9.46734529918955292072e-02, +-9.82804909435327500589e-02, +-1.01803628087157427284e-01, +-1.05242594264867719844e-01, +-1.08597145097841310535e-01, +-1.11867061962988789681e-01, +-1.15052151961296145188e-01, +-1.18152247877890054228e-01, +-1.21167208133862752684e-01, +-1.24096916729885473063e-01, +-1.26941283181660202750e-01, +-1.29700242447243679900e-01, +-1.32373754846295377252e-01, +-1.34961805971292009287e-01, +-1.37464406590764143257e-01, +-1.39881592544604443917e-01, +-1.42213424631507739937e-01, +-1.44459988488595730827e-01, +-1.46621394463294696386e-01, +-1.48697777477524800682e-01, +-1.50689296884269657850e-01, +-1.52596136316595465399e-01, +-1.54418503529190731527e-01, +-1.56156630232500315270e-01, +-1.57810771919529219121e-01, +-1.59381207685401427021e-01, +-1.60868240039743037872e-01, +-1.62272194711985145998e-01, +-1.63593420449666626659e-01, +-1.64832288809824062392e-01, +-1.65989193943563151379e-01, +-1.67064552373901109572e-01, +-1.68058802766975601273e-01, +-1.68972405696717037360e-01, +-1.69805843403086798027e-01, +-1.70559619543971530131e-01, +-1.71234258940853617537e-01, +-1.71830307318344255307e-01, +-1.72348331037702334756e-01, +-1.72788916824434257702e-01, +-1.73152671490098081231e-01, +-1.73440221648409775845e-01, +-1.73652213425782242506e-01, +-1.73789312166397952319e-01, +-1.73852202131942051855e-01, +-1.73841586196111674845e-01, +-1.73758185534021086793e-01, +-1.73602739306629005878e-01, +-1.73376004340306061335e-01, +-1.73078754801670009478e-01, +-1.72711781867818603420e-01, +-1.72275893392080048372e-01, +-1.71771913565416961545e-01, +-1.71200682573611373538e-01, +-1.70563056250360139954e-01, +-1.69859905726417126370e-01, +-1.69092117074913228514e-01, +-1.68260590952989147473e-01, +-1.67366242239875284703e-01, +-1.66409999671557895518e-01, +-1.65392805472166642966e-01, +-1.64315614982222552021e-01, +-1.63179396283883837437e-01, +-1.61985129823331186483e-01, +-1.60733808030429803360e-01, +-1.59426434935813571281e-01, +-1.58064025785527417778e-01, +-1.56647606653372045704e-01, +-1.55178214051094831571e-01, +-1.53656894536566474008e-01, +-1.52084704320088470730e-01, +-1.50462708868975059140e-01, +-1.48791982510548842500e-01, +-1.47073608033699704256e-01, +-1.45308676289147314931e-01, +-1.43498285788550977715e-01, +-1.41643542302611558092e-01, +-1.39745558458309881988e-01, +-1.37805453335422323224e-01, +-1.35824352062461073398e-01, +-1.33803385412180564362e-01, +-1.31743689396791985313e-01, +-1.29646404863030306753e-01, +-1.27512677087215337002e-01, +-1.25343655370452389253e-01, +-1.23140492634104758984e-01, +-1.20904345015691472298e-01, +-1.18636371465341922127e-01, +-1.16337733342949820048e-01, +-1.14009594016166518338e-01, +-1.11653118459372716065e-01, +-1.09269472853762789066e-01, +-1.06859824188683741331e-01, +-1.04425339864360325337e-01, +-1.01967187296145456177e-01, +-9.94865335204263567803e-02, +-9.69845448023236023083e-02, +-9.44623862453117940641e-02, +-9.19212214028948121358e-02, +-8.93622118924671249296e-02, +-8.67865170114848205607e-02, +-8.41952933560805999447e-02, +-8.15896944422443981537e-02, +-7.89708703296961439522e-02, +-7.63399672485739477779e-02, +-7.36981272290610500697e-02, +-7.10464877340710454501e-02, +-6.83861812951113146042e-02, +-6.57183351514422919859e-02, +-6.30440708926501142129e-02, +-6.03645041047437408421e-02, +-5.76807440198948140342e-02, +-5.49938931699267691267e-02, +-5.23050470436661057994e-02, +-4.96152937482609926456e-02, +-4.69257136745778041798e-02, +-4.42373791667729082677e-02, +-4.15513541961495605492e-02, +-3.88686940393953503370e-02, +-3.61904449613011935938e-02, +-3.35176439020573244121e-02, +-3.08513181692228674602e-02, +-2.81924851344595717162e-02, +-2.55421519351213023585e-02, +-2.29013151807887539724e-02, +-2.02709606648342685609e-02, +-1.76520630811025022733e-02, +-1.50455857457888787787e-02, +-1.24524803245954687053e-02, +-9.87368656524285036313e-03, +-7.31013203541311037958e-03, +-4.76273186619807602227e-03, +-2.23238850112297869746e-03, + 2.80008549183706099625e-04, + 2.77358294660976899965e-03, + 5.24747175940274562800e-03, + 7.70082569017439908660e-03, + 1.01328092980087648006e-02, + 1.25426012146140665460e-02, + 1.49293943544662570388e-02, + 1.72923961188884665885e-02, + 1.96308285940195309527e-02, + 2.19439287426209730936e-02, + 2.42309485896793734561e-02, + 2.64911554017603391442e-02, + 2.87238318600733545660e-02, + 3.09282762272103349532e-02, + 3.31038025075217068327e-02, + 3.52497406010981520486e-02, + 3.73654364513253609004e-02, + 3.94502521859858221176e-02, + 4.15035662518817155542e-02, + 4.35247735429537541130e-02, + 4.55132855218787699125e-02, + 4.74685303351244439196e-02, + 4.93899529214478216765e-02, + 5.12770151138242716304e-02, + 5.31291957347935772660e-02, + 5.49459906852194576721e-02, + 5.67269130264521220797e-02, + 5.84714930558940249039e-02, + 6.01792783759655322551e-02, + 6.18498339564735599705e-02, + 6.34827421903864652641e-02, + 6.50776029430226859995e-02, + 6.66340335946605799577e-02, + 6.81516690765814614483e-02, + 6.96301619005592065115e-02, + 7.10691821818139612965e-02, + 7.24684176554465098175e-02, + 7.38275736863740761340e-02, + 7.51463732727930683319e-02, + 7.64245570431912463194e-02, + 7.76618832469397474272e-02, + 7.88581277384926976337e-02, + 8.00130839552289779837e-02, + 8.11265628889681067459e-02, + 8.21983930512013155623e-02, + 8.32284204320703352442e-02, + 8.42165084531432683868e-02, + 8.51625379140240473808e-02, + 8.60664069328434949702e-02, + 8.69280308806818224898e-02, + 8.77473423099686122839e-02, + 8.85242908769151987114e-02, + 8.92588432580306151420e-02, + 8.99509830607803234637e-02, + 9.06007107284422380511e-02, + 9.12080434392217309636e-02, + 9.17730149996878741270e-02, + 9.22956757325926607782e-02, + 9.27760923591415126443e-02, + 9.32143478757788968014e-02, + 9.36105414255621187669e-02, + 9.39647881641913207407e-02, + 9.42772191207702781046e-02, + 9.45479810533706027664e-02, + 9.47772362994778183598e-02, + 9.49651626213951355338e-02, + 9.51119530466846413441e-02, + 9.52178157037280176178e-02, + 9.52829736524876819148e-02, + 9.53076647105531166160e-02, + 9.52921412745576373871e-02, + 9.52366701370536278271e-02, + 9.51415322989309503177e-02, + 9.50070227774735681647e-02, + 9.48334504101390751707e-02, + 9.46211376541590265532e-02, + 9.43704203820504156086e-02, + 9.40816476731309581094e-02, + 9.37551816011396865758e-02, + 9.33913970180541563870e-02, + 9.29906813342047527948e-02, + 9.25534342947849225647e-02, + 9.20800677528557931506e-02, + 9.15710054389489019888e-02, + 9.10266827273659706599e-02, + 9.04475463992783224043e-02, + 8.98340544027328158361e-02, + 8.91866756096650198371e-02, + 8.85058895700238101867e-02, + 8.77921862631190763615e-02, + 8.70460658462897246546e-02, + 8.62680384010083983748e-02, + 8.54586236765221690659e-02, + 8.46183508311429133375e-02, + 8.37477581712920277068e-02, + 8.28473928884114751980e-02, + 8.19178107938471483651e-02, + 8.09595760518180135312e-02, + 7.99732609105757996648e-02, + 7.89594454318716387764e-02, + 7.79187172188340326784e-02, + 7.68516711423724852015e-02, + 7.57589090662164482692e-02, + 7.46410395707000073884e-02, + 7.34986776754032733461e-02, + 7.23324445607601979047e-02, + 7.11429672887474440213e-02, + 6.99308785227581580779e-02, + 6.86968162467783832748e-02, + 6.74414234839716131287e-02, + 6.61653480147834510694e-02, + 6.48692420946761771905e-02, + 6.35537621716019962559e-02, + 6.22195686033254202751e-02, + 6.08673253747022482973e-02, + 5.94976998150253330588e-02, + 5.81113623155428762890e-02, + 5.67089860472591994478e-02, + 5.52912466791220663653e-02, + 5.38588220967053943333e-02, + 5.24123921214928872869e-02, + 5.09526382308646275110e-02, + 4.94802432788957607945e-02, + 4.79958912180662375380e-02, + 4.65002668219884549017e-02, + 4.49940554092515265783e-02, + 4.34779425684853407241e-02, + 4.19526138847447563340e-02, + 4.04187546673120054463e-02, + 3.88770496790168534895e-02, + 3.73281828671714888124e-02, + 3.57728370962169389680e-02, + 3.42116938821758476141e-02, + 3.26454331290065291604e-02, + 3.10747328669506231447e-02, + 2.95002689929673225788e-02, + 2.79227150133440210622e-02, + 2.63427417885741359249e-02, + 2.47610172805882329528e-02, + 2.31782063024293799591e-02, + 2.15949702704538760989e-02, + 2.00119669591453143431e-02, + 1.84298502586232419709e-02, + 1.68492699349288496680e-02, + 1.52708713931675090641e-02, + 1.36952954435869880129e-02, + 1.21231780706691841254e-02, + 1.05551502053105091677e-02, + 8.99183750016553651196e-03, + 7.43386010822696258193e-03, + 5.88183246471273707412e-03, + 4.33636307232945251988e-03, + 2.79805428998205086427e-03, + 1.26750212499337003291e-03, +-2.54703971099550386531e-04, +-1.76798130311027175757e-03, +-3.27175412906725469539e-03, +-4.76545385331804925710e-03, +-6.24851921581533794464e-03, +-7.72039647752874400727e-03, +-9.18053960192777122884e-03, +-1.06284104324833178490e-02, +-1.20634788661366718077e-02, +-1.34852230226875247771e-02, +-1.48931294100519973078e-02, +-1.62866930853476296615e-02, +-1.76654178117594401476e-02, +-1.90288162111466874205e-02, +-2.03764099123495759369e-02, +-2.17077296951579609696e-02, +-2.30223156299061669505e-02, +-2.43197172126588360974e-02, +-2.55994934959561624976e-02, +-2.68612132150869431513e-02, +-2.81044549098614510063e-02, +-2.93288070418574950415e-02, +-3.05338681071131295974e-02, +-3.17192467442452205595e-02, +-3.28845618379712614776e-02, +-3.40294426180154721551e-02, +-3.51535287533818185945e-02, +-3.62564704419792716017e-02, +-3.73379284955845242022e-02, +-3.83975744201309962533e-02, +-3.94350904913155775322e-02, +-4.04501698255130062720e-02, +-4.14425164459938585870e-02, +-4.24118453444415760556e-02, +-4.33578825377650758921e-02, +-4.42803651202084772032e-02, +-4.51790413107587551789e-02, +-4.60536704958539877541e-02, +-4.69040232673985507672e-02, +-4.77298814560914094751e-02, +-4.85310381600771723054e-02, +-4.93072977689298017068e-02, +-5.00584759829825892696e-02, +-5.07843998280173986037e-02, +-5.14849076653303427964e-02, +-5.21598491971914657306e-02, +-5.28090854677170859488e-02, +-5.34324888591782357072e-02, +-5.40299430837655400572e-02, +-5.46013431708381041796e-02, +-5.51465954496810906171e-02, +-5.56656175277993395256e-02, +-5.61583382647804357779e-02, +-5.66246977417538960298e-02, +-5.70646472264832865795e-02, +-5.74781491341238848225e-02, +-5.78651769836829588112e-02, +-5.82257153502198851469e-02, +-5.85597598128258789441e-02, +-5.88673168984241990120e-02, +-5.91484040214318093631e-02, +-5.94030494193287308957e-02, +-5.96312920841784027681e-02, +-5.98331816901454746627e-02, +-6.00087785170606569096e-02, +-6.01581533700810480725e-02, +-6.02813874954959694197e-02, +-6.03785724927326447609e-02, +-6.04498102226119424230e-02, +-6.04952127119116611631e-02, +-6.05149020542914278797e-02, +-6.05090103076376881197e-02, +-6.04776793878847099273e-02, +-6.04210609593744951695e-02, +-6.03393163218124903291e-02, +-6.02326162938837256222e-02, +-6.01011410935896536745e-02, +-5.99450802153716350018e-02, +-5.97646323040843391317e-02, +-5.95600050258849322837e-02, +-5.93314149361059764431e-02, +-5.90790873441773764507e-02, +-5.88032561756684640786e-02, +-5.85041638315173181950e-02, +-5.81820610445198463379e-02, +-5.78372067331465664064e-02, +-5.74698678527617162759e-02, +-5.70803192443151696800e-02, +-5.66688434805820984153e-02, +-5.62357307100216502471e-02, +-5.57812784983319834287e-02, +-5.53057916677746758127e-02, +-5.48095821343453915020e-02, +-5.42929687428649263015e-02, +-5.37562771000702349644e-02, +-5.31998394057807341695e-02, +-5.26239942822169029513e-02, +-5.20290866015511582754e-02, +-5.14154673117670768523e-02, +-5.07834932609073572141e-02, +-5.01335270197884388943e-02, +-4.94659367032617980353e-02, +-4.87810957901005926018e-02, +-4.80793829415919610204e-02, +-4.73611818189140221236e-02, +-4.66268808993793651418e-02, +-4.58768732916221277929e-02, +-4.51115565498113532672e-02, +-4.43313324869706107401e-02, +-4.35366069874822472774e-02, +-4.27277898188581847783e-02, +-4.19052944428566706558e-02, +-4.10695378260253277092e-02, +-4.02209402497498702544e-02, +-3.93599251198885058400e-02, +-3.84869187760717781921e-02, +-3.76023503007467674308e-02, +-3.67066513280452297319e-02, +-3.58002558525536487832e-02, +-3.48836000380640318119e-02, +-3.39571220263849699039e-02, +-3.30212617462878818553e-02, +-3.20764607226682249563e-02, +-3.11231618859974003277e-02, +-3.01618093821427596390e-02, +-2.91928483826300218251e-02, +-2.82167248954252464221e-02, +-2.72338855763107207109e-02, +-2.62447775409285488646e-02, +-2.52498481775659533444e-02, +-2.42495449607560524530e-02, +-2.32443152657647901516e-02, +-2.22346061840382018537e-02, +-2.12208643396787077773e-02, +-2.02035357070221716080e-02, +-1.91830654293842946256e-02, +-1.81598976390459701524e-02, +-1.71344752785447841659e-02, +-1.61072399233397958729e-02, +-1.50786316059164128556e-02, +-1.40490886413957953571e-02, +-1.30190474547137412242e-02, +-1.19889424094323342185e-02, +-1.09592056382471266657e-02, +-9.93026687525074697183e-03, +-8.90255329001433948211e-03, +-7.87648932354562125724e-03, +-6.85249652618241146540e-03, +-5.83099339747908569642e-03, +-4.81239522814202146106e-03, +-3.79711394406930576734e-03, +-2.78555795254968683455e-03, +-1.77813199067227692071e-03, +-7.75236976000132386663e-04, + 2.22730140442126654798e-04, + 1.21537651881706244492e-03, + 2.20231357271108733539e-03, + 3.18315710891246220898e-03, + 4.15752746468348553799e-03, + 5.12504964248380791986e-03, + 6.08535344210042478813e-03, + 7.03807359014245199208e-03, + 7.98284986685961206465e-03, + 8.91932723024580452476e-03, + 9.84715593738785290034e-03, + 1.07659916630240357766e-02, + 1.16754956152756248638e-02, + 1.25753346485176220604e-02, + 1.34651813733560731662e-02, + 1.43447142636787781933e-02, + 1.52136177607511777904e-02, + 1.60715823743268690360e-02, + 1.69183047807457617728e-02, + 1.77534879179936204430e-02, + 1.85768410776981605925e-02, + 1.93880799940382604618e-02, + 2.01869269295435888045e-02, + 2.09731107577651766649e-02, + 2.17463670427963037812e-02, + 2.25064381156266125894e-02, + 2.32530731473125917841e-02, + 2.39860282189490944815e-02, + 2.47050663884288181082e-02, + 2.54099577539762186418e-02, + 2.61004795144461655687e-02, + 2.67764160263764816605e-02, + 2.74375588577874841845e-02, + 2.80837068387202806741e-02, + 2.87146661085097808230e-02, + 2.93302501597869115513e-02, + 2.99302798792087168533e-02, + 3.05145835849139068774e-02, + 3.10829970607048658437e-02, + 3.16353635869560598226e-02, + 3.21715339682534032240e-02, + 3.26913665577675052742e-02, + 3.31947272783659833029e-02, + 3.36814896404726560331e-02, + 3.41515347566807569990e-02, + 3.46047513531298478462e-02, + 3.50410357776568884280e-02, + 3.54602920047340924858e-02, + 3.58624316372060172875e-02, + 3.62473739048404727803e-02, + 3.66150456597097023748e-02, + 3.69653813684179058385e-02, + 3.72983231011940682964e-02, + 3.76138205178691634178e-02, + 3.79118308507581658340e-02, + 3.81923188844700278732e-02, + 3.84552569326661666804e-02, + 3.87006248117945095277e-02, + 3.89284098118221136287e-02, + 3.91386066639944005252e-02, + 3.93312175056476295842e-02, + 3.95062518421033306848e-02, + 3.96637265056755394799e-02, + 3.98036656118202977761e-02, + 3.99261005124597820326e-02, + 4.00310697465144360585e-02, + 4.01186189876763035778e-02, + 4.01888009894591641258e-02, + 4.02416755275608953313e-02, + 4.02773093395744422041e-02, + 4.02957760620868618573e-02, + 4.02971561652026855072e-02, + 4.02815368845340013304e-02, + 4.02490121506946865737e-02, + 4.01996825163432602857e-02, + 4.01336550808131173329e-02, + 4.00510434123766412284e-02, + 3.99519674681838021790e-02, + 3.98365535119223901361e-02, + 3.97049340292425986809e-02, + 3.95572476409943238340e-02, + 3.93936390143226622396e-02, + 3.92142587716682866628e-02, + 3.90192633977227906761e-02, + 3.88088151443859719070e-02, + 3.85830819337740632546e-02, + 3.83422372593309676581e-02, + 3.80864600850902706997e-02, + 3.78159347431409609275e-02, + 3.75308508293468318096e-02, + 3.72314030973733209318e-02, + 3.69177913510723085255e-02, + 3.65902203352790472701e-02, + 3.62488996250740352911e-02, + 3.58940435135636018438e-02, + 3.55258708982338911042e-02, + 3.51446051659309519066e-02, + 3.47504740765239503175e-02, + 3.43437096453047957523e-02, + 3.39245480241803926136e-02, + 3.34932293817127510471e-02, + 3.30499977820627663383e-02, + 3.25951010628938789293e-02, + 3.21287907122915217251e-02, + 3.16513217447548164674e-02, + 3.11629525763171093267e-02, + 3.06639448988514501382e-02, + 3.01545635536184866710e-02, + 2.96350764041116987446e-02, + 2.91057542082603579181e-02, + 2.85668704900414009706e-02, + 2.80187014105628129368e-02, + 2.74615256386703497637e-02, + 2.68956242211381771345e-02, + 2.63212804524964143205e-02, + 2.57387797445546746833e-02, + 2.51484094956766456030e-02, + 2.45504589598617914414e-02, + 2.39452191156906725455e-02, + 2.33329825351894608321e-02, + 2.27140432526683408443e-02, + 2.20886966335908999093e-02, + 2.14572392435271874778e-02, + 2.08199687172471933905e-02, + 2.01771836280079629178e-02, + 1.95291833570884962312e-02, + 1.88762679636269269101e-02, + 1.82187380548123403767e-02, + 1.75568946564845403124e-02, + 1.68910390841945853846e-02, + 1.62214728147774996103e-02, + 1.55484973584896369464e-02, + 1.48724141317607399387e-02, + 1.41935243306124080076e-02, + 1.35121288047925294795e-02, + 1.28285279326754275003e-02, + 1.21430214969758445281e-02, + 1.14559085613274869858e-02, + 1.07674873477713456404e-02, + 1.00780551152029641815e-02, + 9.38790803882408146641e-03, + 8.69734109064560119429e-03, + 8.00664792108640895052e-03, + 7.31612074171312902482e-03, + 6.62605020916498532735e-03, + 5.93672531030635993593e-03, + 5.24843324865020312286e-03, + 4.56145933209378684481e-03, + 3.87608686200798923521e-03, + 3.19259702372048361982e-03, + 2.51126877843176705626e-03, + 1.83237875660391988202e-03, + 1.15620115285868549186e-03, + 4.83007622422852007059e-04, +-1.86932820843070034112e-04, +-8.53353904797455329115e-04, +-1.51599219771675255281e-03, +-2.17458720530792556924e-03, +-2.82888146600037857989e-03, +-3.47862064448672828401e-03, +-4.12355362347965707925e-03, +-4.76343259365718217635e-03, +-5.39801314176371720144e-03, +-6.02705433684159932323e-03, +-6.65031881456398799024e-03, +-7.26757285964317947813e-03, +-7.87858648628854928153e-03, +-8.48313351669007821576e-03, +-9.08099165750268083608e-03, +-9.67194257431004678072e-03, +-1.02557719640449674509e-02, +-1.08322696253466653482e-02, +-1.14012295268339416271e-02, +-1.19624498732761111452e-02, +-1.25157331696445651287e-02, +-1.30608862830260651078e-02, +-1.35977205023845738180e-02, +-1.41260515961539080687e-02, +-1.46456998676501564532e-02, +-1.51564902082884610246e-02, +-1.56582521485937077588e-02, +-1.61508199069943896020e-02, +-1.66340324363880263936e-02, +-1.71077334684716746149e-02, +-1.75717715558275228149e-02, +-1.80260001117568194329e-02, +-1.84702774478586080609e-02, +-1.89044668093441003975e-02, +-1.93284364080869922042e-02, +-1.97420594534034529732e-02, +-2.01452141805614354242e-02, +-2.05377838770183090977e-02, +-2.09196569063852221004e-02, +-2.12907267301215390176e-02, +-2.16508919269584217127e-02, +-2.20000562100566773860e-02, +-2.23381284419012192399e-02, +-2.26650226469371808558e-02, +-2.29806580219539050014e-02, +-2.32849589442222955349e-02, +-2.35778549773940013234e-02, +-2.38592808751701725145e-02, +-2.41291765827496146324e-02, +-2.43874872360661625048e-02, +-2.46341631588262027774e-02, +-2.48691598573592027865e-02, +-2.50924380132932847709e-02, +-2.53039634740697960691e-02, +-2.55037072413113186098e-02, +-2.56916454570593408291e-02, +-2.58677593878966008423e-02, +-2.60320354069717534162e-02, +-2.61844649739453247395e-02, +-2.63250446128731642459e-02, +-2.64537758880496950975e-02, +-2.65706653778289558776e-02, +-2.66757246464459155111e-02, +-2.67689702138592805492e-02, +-2.68504235236379437679e-02, +-2.69201109089152179621e-02, +-2.69780635564342181898e-02, +-2.70243174687087896191e-02, +-2.70589134243261995871e-02, +-2.70818969364167577707e-02, +-2.70933182093176481986e-02, +-2.70932320934577017257e-02, +-2.70816980384915410862e-02, +-2.70587800447114543156e-02, +-2.70245466127663376554e-02, +-2.69790706917171427270e-02, +-2.69224296254590607369e-02, +-2.68547050975419879237e-02, +-2.67759830744198866481e-02, +-2.66863537471611969587e-02, +-2.65859114716531889921e-02, +-2.64747547073322930800e-02, +-2.63529859544745573285e-02, +-2.62207116900796607939e-02, +-2.60780423023825730366e-02, +-2.59250920240284947471e-02, +-2.57619788639449828760e-02, +-2.55888245379471308827e-02, +-2.54057543981124761556e-02, +-2.52128973609604678519e-02, +-2.50103858344739478359e-02, +-2.47983556439997539222e-02, +-2.45769459570643403201e-02, +-2.43462992071435090080e-02, +-2.41065610164222128564e-02, +-2.38578801175844575078e-02, +-2.36004082746693114037e-02, +-2.33343002030331689300e-02, +-2.30597134884559483436e-02, +-2.27768085054302904524e-02, +-2.24857483346725776918e-02, +-2.21866986798954189675e-02, +-2.18798277838799307138e-02, +-2.15653063438876642366e-02, +-2.12433074264517691987e-02, +-2.09140063815867055519e-02, +-2.05775807564556566243e-02, +-2.02342102085360346642e-02, +-1.98840764183222142025e-02, +-1.95273630016047500257e-02, +-1.91642554213670816832e-02, +-1.87949408993371563925e-02, +-1.84196083272362247374e-02, +-1.80384481777610752862e-02, +-1.76516524153425696797e-02, +-1.72594144067167720724e-02, +-1.68619288313498413845e-02, +-1.64593915917550098760e-02, +-1.60519997237402040069e-02, +-1.56399513066264282679e-02, +-1.52234453734734331148e-02, +-1.48026818213531103502e-02, +-1.43778613217079923037e-02, +-1.39491852308316760523e-02, +-1.35168555005115483686e-02, +-1.30810745888681710658e-02, +-1.26420453714316226301e-02, +-1.21999710524887047813e-02, +-1.17550550767402828961e-02, +-1.13075010413035727252e-02, +-1.08575126080952908542e-02, +-1.04052934166326063736e-02, +-9.95104699728536351566e-03, +-9.49497668501652312967e-03, +-9.03728553364356763933e-03, +-8.57817623065582068875e-03, +-8.11785101262214349449e-03, +-7.65651158122056946231e-03, +-7.19435901992488725798e-03, +-6.73159371137851351291e-03, +-6.26841525548942068990e-03, +-5.80502238827697216589e-03, +-5.34161290150089295564e-03, +-4.87838356310490647849e-03, +-4.41553003850264462471e-03, +-3.95324681273798422126e-03, +-3.49172711354636287548e-03, +-3.03116283534747218975e-03, +-2.57174446419663202748e-03, +-2.11366100372138449731e-03, +-1.65709990207213789248e-03, +-1.20224697991074881177e-03, +-7.49286359465203312402e-04, +-2.98400394673150758020e-04, + 1.50230397559290287587e-04, + 5.96427404960260163468e-04, + 1.04001398633389997676e-03, + 1.48081553681653948010e-03, + 1.91865955192711671630e-03, + 2.35337569038958404136e-03, + 2.78479583570576333731e-03, + 3.21275415646031688166e-03, + 3.63708716533605539573e-03, + 4.05763377682291995208e-03, + 4.47423536360066955581e-03, + 4.88673581157838838457e-03, + 5.29498157357465894235e-03, + 5.69882172162047926506e-03, + 6.09810799787139853900e-03, + 6.49269486411187517899e-03, + 6.88243954983998491859e-03, + 7.26720209891677272618e-03, + 7.64684541476874993227e-03, + 8.02123530413159993580e-03, + 8.39024051932213063565e-03, + 8.75373279902990839019e-03, + 9.11158690761618844656e-03, + 9.46368067291306243327e-03, + 9.80989502251233651264e-03, + 1.01501140185368699670e-02, + 1.04842248908878447194e-02, + 1.08121180689596009528e-02, + 1.11336872118183785596e-02, + 1.14488292368375710328e-02, + 1.17574443467867335855e-02, + 1.20594360553697797084e-02, + 1.23547112112087492664e-02, + 1.26431800202723137322e-02, + 1.29247560667452802280e-02, + 1.31993563323394361153e-02, + 1.34669012140451026943e-02, + 1.37273145403230718842e-02, + 1.39805235857388930609e-02, + 1.42264590840399576116e-02, + 1.44650552396788801418e-02, + 1.46962497377853603536e-02, + 1.49199837525900817770e-02, + 1.51362019543059365262e-02, + 1.53448525144697818512e-02, + 1.55458871097522988158e-02, + 1.57392609242401407266e-02, + 1.59249326501989980909e-02, + 1.61028644873237487822e-02, + 1.62730221404839558996e-02, + 1.64353748159745995105e-02, + 1.65898952162792344411e-02, + 1.67365595333573702330e-02, + 1.68753474404654685292e-02, + 1.70062420825228405308e-02, + 1.71292300650343690127e-02, + 1.72443014415816948948e-02, + 1.73514496998961910423e-02, + 1.74506717465267233158e-02, + 1.75419678901157470585e-02, + 1.76253418232991503067e-02, + 1.77008006032431768062e-02, + 1.77683546308354950449e-02, + 1.78280176285450023266e-02, + 1.78798066169677284665e-02, + 1.79237418900749095885e-02, + 1.79598469891815541721e-02, + 1.79881486756524357207e-02, + 1.80086769023645003329e-02, + 1.80214647839439801036e-02, + 1.80265485657978320744e-02, + 1.80239675919585257136e-02, + 1.80137642717629609113e-02, + 1.79959840453853894826e-02, + 1.79706753482452019632e-02, + 1.79378895743111561878e-02, + 1.78976810383233188306e-02, + 1.78501069369546815080e-02, + 1.77952273089348571300e-02, + 1.77331049941585293384e-02, + 1.76638055918014250101e-02, + 1.75873974174670689996e-02, + 1.75039514593883366311e-02, + 1.74135413337067820883e-02, + 1.73162432388551425222e-02, + 1.72121359090659648006e-02, + 1.71013005670323306462e-02, + 1.69838208757447130248e-02, + 1.68597828895295613616e-02, + 1.67292750043147309125e-02, + 1.65923879071472879509e-02, + 1.64492145249898746862e-02, + 1.62998499728209574056e-02, + 1.61443915010654574782e-02, + 1.59829384423819872985e-02, + 1.58155921578329479449e-02, + 1.56424559824643004402e-02, + 1.54636351703211580993e-02, + 1.52792368389266484952e-02, + 1.50893699132506348831e-02, + 1.48941450691946284529e-02, + 1.46936746766213478105e-02, + 1.44880727419542387757e-02, + 1.42774548503756936596e-02, + 1.40619381076500047506e-02, + 1.38416410815988405458e-02, + 1.36166837432563775367e-02, + 1.33871874077307433104e-02, + 1.31532746747999255282e-02, + 1.29150693692685249875e-02, + 1.26726964811125480254e-02, + 1.24262821054400597609e-02, + 1.21759533822933443264e-02, + 1.19218384363212748234e-02, + 1.16640663163469111840e-02, + 1.14027669348586990772e-02, + 1.11380710074510391738e-02, + 1.08701099922405512027e-02, + 1.05990160292857588803e-02, + 1.03249218800347264402e-02, + 1.00479608668283364181e-02, + 9.76826681248407595326e-03, + 9.48597397998680001707e-03, + 9.20121701231205180171e-03, + 8.91413087240663405686e-03, + 8.62485078335300560382e-03, + 8.33351216874106057175e-03, + 8.04025059327335284154e-03, + 7.74520170362733365033e-03, + 7.44850116959968472363e-03, + 7.15028462555652392224e-03, + 6.85068761221313375642e-03, + 6.54984551876693164157e-03, + 6.24789352540736173808e-03, + 5.94496654622468298501e-03, + 5.64119917254172174859e-03, + 5.33672561668945780872e-03, + 5.03167965625017643561e-03, + 4.72619457878821046942e-03, + 4.42040312709122713147e-03, + 4.11443744494245557813e-03, + 3.80842902344421868274e-03, + 3.50250864791438413365e-03, + 3.19680634537424174582e-03, + 2.89145133264915015631e-03, + 2.58657196509964968506e-03, + 2.28229568600325869593e-03, + 1.97874897660506266980e-03, + 1.67605730685465247574e-03, + 1.37434508684857771554e-03, + 1.07373561899400072825e-03, + 7.74351050912206037222e-04, + 4.76312329096932108620e-04, + 1.79739153344913828647e-04, +-1.15250068026150436743e-04, +-4.08538262157430215240e-04, +-7.00009734810518881830e-04, +-9.89550212697529359140e-04, +-1.27704688496522110984e-03, +-1.56238844381914230262e-03, +-1.84546512427596291067e-03, +-2.12616874302977649017e-03, +-2.40439273642179809562e-03, +-2.68003219750039467159e-03, +-2.95298391216083011210e-03, +-3.22314639435426720723e-03, +-3.49041992035452591087e-03, +-3.75470656207426648626e-03, +-4.01591021941965966441e-03, +-4.27393665167596914500e-03, +-4.52869350791463860101e-03, +-4.78009035641408387002e-03, +-5.02803871308742881402e-03, +-5.27245206890878791856e-03, +-5.51324591633307794364e-03, +-5.75033777470175880286e-03, +-5.98364721463032038506e-03, +-6.21309588137129026331e-03, +-6.43860751714846711591e-03, +-6.66010798245885143193e-03, +-6.87752527633716734257e-03, +-7.09078955558135361203e-03, +-7.29983315293484570641e-03, +-7.50459059422442856246e-03, +-7.70499861445137022159e-03, +-7.90099617283428028169e-03, +-8.09252446680348673513e-03, +-8.27952694494581836748e-03, +-8.46194931890021165288e-03, +-8.63973957420479179992e-03, +-8.81284798009584514900e-03, +-8.98122709826090423468e-03, +-9.14483179054685624276e-03, +-9.30361922562642808254e-03, +-9.45754888462495800494e-03, +-9.60658256571109842037e-03, +-9.75068438765514661215e-03, +-9.88982079235872779677e-03, +-1.00239605463608785763e-02, +-1.01530747413246837108e-02, +-1.02771367935108499936e-02, +-1.03961224422430293518e-02, +-1.05100097473716045521e-02, +-1.06187790857425311958e-02, +-1.07224131466778661165e-02, +-1.08208969264758890494e-02, +-1.09142177219381259629e-02, +-1.10023651229317290939e-02, +-1.10853310039956218930e-02, +-1.11631095149994884197e-02, +-1.12356970708646971419e-02, +-1.13030923403568215463e-02, +-1.13652962339602110059e-02, +-1.14223118908440956359e-02, +-1.14741446649318026840e-02, +-1.15208021100836454503e-02, +-1.15622939644049946284e-02, +-1.15986321336910645080e-02, +-1.16298306740207010868e-02, +-1.16559057735113307669e-02, +-1.16768757332475214827e-02, +-1.16927609473963332182e-02, +-1.17035838825226608945e-02, +-1.17093690561177760784e-02, +-1.17101430143551586693e-02, +-1.17059343090872795129e-02, +-1.16967734740980097013e-02, +-1.16826930006248379257e-02, +-1.16637273121658596037e-02, +-1.16399127385864407935e-02, +-1.16112874895409699111e-02, +-1.15778916272246922003e-02, +-1.15397670384720374415e-02, +-1.14969574062164479888e-02, +-1.14495081803284975280e-02, +-1.13974665478479546959e-02, +-1.13408814026266253211e-02, +-1.12798033143984600957e-02, +-1.12142844972935168402e-02, +-1.11443787778127377519e-02, +-1.10701415622809114236e-02, +-1.09916298037944538957e-02, +-1.09089019686816925125e-02, +-1.08220180024931385970e-02, +-1.07310392955389764802e-02, +-1.06360286479915983754e-02, +-1.05370502345710423397e-02, +-1.04341695688310136247e-02, +-1.03274534670632443106e-02, +-1.02169700118386209270e-02, +-1.01027885152025192345e-02, +-9.98497948154308812008e-03, +-9.86361457015006402871e-03, +-9.73876655748246930488e-03, +-9.61050929916365190286e-03, +-9.47891769172138146105e-03, +-9.34406763409175583623e-03, +-9.20603598890469380922e-03, +-9.06490054356958417647e-03, +-8.92073997117914622990e-03, +-8.77363379124968326139e-03, +-8.62366233031589164704e-03, +-8.47090668239862398803e-03, +-8.31544866936306283078e-03, +-8.15737080118616487978e-03, +-7.99675623615058242533e-03, +-7.83368874098351944402e-03, +-7.66825265095798756787e-03, +-7.50053282997436773782e-03, +-7.33061463064018075525e-03, +-7.15858385436481461928e-03, +-6.98452671148786126409e-03, +-6.80852978145714965441e-03, +-6.63067997307481386826e-03, +-6.45106448482760802543e-03, +-6.26977076531890029770e-03, +-6.08688647381931853542e-03, +-5.90249944095203298716e-03, +-5.71669762953000513278e-03, +-5.52956909556100162373e-03, +-5.34120194943696596085e-03, +-5.15168431732329797079e-03, +-4.96110430276443595266e-03, +-4.76954994852103134756e-03, +-4.57710919865432410564e-03, +-4.38386986087277181340e-03, +-4.18991956915663876782e-03, +-3.99534574667439676410e-03, +-3.80023556900675307108e-03, +-3.60467592769156538676e-03, +-3.40875339410503987864e-03, +-3.21255418369197943973e-03, +-3.01616412055992575564e-03, +-2.81966860245005685598e-03, +-2.62315256609809257030e-03, +-2.42670045299875130826e-03, +-2.23039617558575898118e-03, +-2.03432308384080993632e-03, +-1.83856393234277533909e-03, +-1.64320084776991355742e-03, +-1.44831529686655904529e-03, +-1.25398805488530435195e-03, +-1.06029917451672204415e-03, +-8.67327955316482155854e-04, +-6.75152913641518712638e-04, +-4.83851753104545291573e-04, +-2.93501335557769932588e-04, +-1.04177652615230481180e-04, + 8.40442022771478958144e-05, + 2.71090061213828637746e-04, + 4.56886708636217294885e-04, + 6.41361907564611910364e-04, + 8.24444425246958221068e-04, + 1.00606405821750295726e-03, + 1.18615165675600578790e-03, + 1.36463914874257485378e-03, + 1.54145956289825905236e-03, + 1.71654705140769636706e-03, + 1.88983691191461173828e-03, + 2.06126560888645086675e-03, + 2.23077079434063144103e-03, + 2.39829132792830895110e-03, + 2.56376729636941056573e-03, + 2.72714003223500402184e-03, + 2.88835213207216685155e-03, + 3.04734747386685260462e-03, + 3.20407123384176817371e-03, + 3.35846990258462183704e-03, + 3.51049130050470068257e-03, + 3.66008459261367522647e-03, + 3.80720030262936314294e-03, + 3.95179032639856198800e-03, + 4.09380794463911311387e-03, + 4.23320783499702736619e-03, + 4.36994608342004212803e-03, + 4.50398019484403704799e-03, + 4.63526910319382156461e-03, + 4.76377318069614620610e-03, + 4.88945424650618146178e-03, + 5.01227557464674778470e-03, + 5.13220190126144337750e-03, + 5.24919943118207308480e-03, + 5.36323584381190321402e-03, + 5.47428029832571112767e-03, + 5.58230343818897148389e-03, + 5.68727739499729628703e-03, + 5.78917579163970574818e-03, + 5.88797374478673089110e-03, + 5.98364786670789981782e-03, + 6.07617626642060343345e-03, + 6.16553855017385084303e-03, + 6.25171582127166582804e-03, + 6.33469067923863194541e-03, + 6.41444721833308011821e-03, + 6.49097102541174898749e-03, + 6.56424917715103632687e-03, + 6.63427023662958338657e-03, + 6.70102424927795491810e-03, + 6.76450273820044644529e-03, + 6.82469869887525251023e-03, + 6.88160659323871527759e-03, + 6.93522234316026366108e-03, + 6.98554332331408935064e-03, + 7.03256835345506155222e-03, + 7.07629769010476809138e-03, + 7.11673301765615093362e-03, + 7.15387743890304877992e-03, + 7.18773546500291789924e-03, + 7.21831300488032408247e-03, + 7.24561735407938580650e-03, + 7.26965718307318129604e-03, + 7.29044252503875406940e-03, + 7.30798476310635155423e-03, + 7.32229661709144288850e-03, + 7.33339212971884264747e-03, + 7.34128665234775375920e-03, + 7.34599683020745793799e-03, + 7.34754058715258225737e-03, + 7.34593710994830336597e-03, + 7.34120683209452638829e-03, + 7.33337141719967496728e-03, + 7.32245374191355016119e-03, + 7.30847787843014878861e-03, + 7.29146907657012011139e-03, + 7.27145374545387114529e-03, + 7.24845943477565521351e-03, + 7.22251481568945107037e-03, + 7.19364966131744686118e-03, + 7.16189482689201083881e-03, + 7.12728222954231872138e-03, + 7.08984482773655864257e-03, + 7.04961660039112210374e-03, + 7.00663252565801673161e-03, + 6.96092855940177307472e-03, + 6.91254161337735619636e-03, + 6.86150953312070904788e-03, + 6.80787107556324582597e-03, + 6.75166588638215301593e-03, + 6.69293447709806265528e-03, + 6.63171820193170571955e-03, + 6.56805923443159328512e-03, + 6.50200054388410785683e-03, + 6.43358587151825807998e-03, + 6.36285970651646794888e-03, + 6.28986726184373092646e-03, + 6.21465444990643503531e-03, + 6.13726785805332464285e-03, + 6.05775472392990760317e-03, + 5.97616291069856791357e-03, + 5.89254088213594148099e-03, + 5.80693767761965816410e-03, + 5.71940288701587758180e-03, + 5.62998662548002196115e-03, + 5.53873950818146131014e-03, + 5.44571262496510149348e-03, + 5.35095751496040238082e-03, + 5.25452614115022934027e-03, + 5.15647086491062122543e-03, + 5.05684442053339500839e-03, + 4.95569988974256699088e-03, + 4.85309067621648645985e-03, + 4.74907048012647350216e-03, + 4.64369327270371719946e-03, + 4.53701327084515566163e-03, + 4.42908491176951992635e-03, + 4.31996282773485212186e-03, + 4.20970182082771107734e-03, + 4.09835683783572966160e-03, + 3.98598294521311340144e-03, + 3.87263530415101094040e-03, + 3.75836914576165720403e-03, + 3.64323974638825019007e-03, + 3.52730240304928790995e-03, + 3.41061240902878646739e-03, + 3.29322502962129748730e-03, + 3.17519547804233142826e-03, + 3.05657889151338601694e-03, + 2.93743030753160130203e-03, + 2.81780464033296821486e-03, + 2.69775665755896121301e-03, + 2.57734095713514719389e-03, + 2.45661194437134461702e-03, + 2.33562380929147129019e-03, + 2.21443050420279223534e-03, + 2.09308572151161147862e-03, + 1.97164287179554201940e-03, + 1.85015506213867531038e-03, + 1.72867507473943343883e-03, + 1.60725534579748128607e-03, + 1.48594794468843234732e-03, + 1.36480455343317803527e-03, + 1.24387644646943291808e-03, + 1.12321447073277739387e-03, + 1.00286902605367005473e-03, + 8.82890045877847201225e-04, + 7.63326978315998568199e-04, + 6.44228767529792380013e-04, + 5.25643835459782418976e-04, + 4.07620063901896608968e-04, + 2.90204776937506045247e-04, + 1.73444723723805766706e-04, + 5.73860616484244659592e-05, +-5.79256601447129809831e-05, +-1.72445516855139978872e-04, +-2.86129223744603178401e-04, +-3.98933151471683798521e-04, +-5.10814341036775051638e-04, +-6.21730518333987194034e-04, +-7.31640108305292775383e-04, +-8.40502248693749103720e-04, +-9.48276803391555388537e-04, +-1.05492437538016840815e-03, +-1.16040631925863960139e-03, +-1.26468475335793167046e-03, +-1.36772257143744795961e-03, +-1.46948345396231690001e-03, +-1.56993187895820992227e-03, +-1.66903313244173671925e-03, +-1.76675331842487395514e-03, +-1.86305936849075486246e-03, +-1.95791905094055886799e-03, +-2.05130097950870097026e-03, +-2.14317462164644121497e-03, +-2.23351030637205421117e-03, +-2.32227923168745655630e-03, +-2.40945347156019864382e-03, +-2.49500598247101752769e-03, +-2.57891060952624437755e-03, +-2.66114209213571661222e-03, +-2.74167606925580006200e-03, +-2.82048908419860059130e-03, +-2.89755858900738426376e-03, +-2.97286294839969704451e-03, +-3.04638144327833843006e-03, +-3.11809427381250833106e-03, +-3.18798256208930414976e-03, +-3.25602835433819615824e-03, +-3.32221462272949338845e-03, +-3.38652526674922864716e-03, +-3.44894511415224942069e-03, +-3.50945992149601917673e-03, +-3.56805637425754813494e-03, +-3.62472208653601482564e-03, +-3.67944560034401835918e-03, +-3.73221638449032109761e-03, +-3.78302483305743104600e-03, +-3.83186226347697993233e-03, +-3.87872091420681094562e-03, +-3.92359394201303914723e-03, +-3.96647541886111301701e-03, +-4.00736032841956212047e-03, +-4.04624456218095809173e-03, +-4.08312491520368761599e-03, +-4.11799908147960237043e-03, +-4.15086564893147550587e-03, +-4.18172409404541419592e-03, +-4.21057477614258761356e-03, +-4.23741893129556731340e-03, +-4.26225866589410255086e-03, +-4.28509694986558761776e-03, +-4.30593760955555893838e-03, +-4.32478532027361865092e-03, +-4.34164559851025946141e-03, +-4.35652479383043678834e-03, +-4.36943008044940375129e-03, +-4.38036944849687272935e-03, +-4.38935169497548655082e-03, +-4.39638641441941844384e-03, +-4.40148398925969356471e-03, +-4.40465557990201740657e-03, +-4.40591311452397972614e-03, +-4.40526927859759102890e-03, +-4.40273750414399336200e-03, +-4.39833195872687317957e-03, +-4.39206753419116562726e-03, +-4.38395983515392842489e-03, +-4.37402516725410826781e-03, +-4.36228052516814471251e-03, +-4.34874358039834783829e-03, +-4.33343266884099378305e-03, +-4.31636677814128347924e-03, +-4.29756553484226828249e-03, +-4.27704919133478460302e-03, +-4.25483861261575103258e-03, +-4.23095526286197242544e-03, +-4.20542119182673330285e-03, +-4.17825902106652539991e-03, +-4.14949193000528453179e-03, +-4.11914364184333848390e-03, +-4.08723840931864319803e-03, +-4.05380100032764340012e-03, +-4.01885668341308427420e-03, +-3.98243121312639048598e-03, +-3.94455081527187324114e-03, +-3.90524217204034265055e-03, +-3.86453240703949710971e-03, +-3.82244907022857112119e-03, +-3.77902012276458334344e-03, +-3.73427392176791782957e-03, +-3.68823920501411533363e-03, +-3.64094507555994461798e-03, +-3.59242098631046497328e-03, +-3.54269672453505143905e-03, +-3.49180239633924225512e-03, +-3.43976841109999795926e-03, +-3.38662546587152699790e-03, +-3.33240452976901182711e-03, +-3.27713682833726460339e-03, +-3.22085382791172753977e-03, +-3.16358721997866921757e-03, +-3.10536890554190866259e-03, +-3.04623097950279270868e-03, +-2.98620571506079835605e-03, +-2.92532554814109750294e-03, +-2.86362306185669341502e-03, +-2.80113097101106212072e-03, +-2.73788210664884781517e-03, +-2.67390940066071719841e-03, +-2.60924587044905360173e-03, +-2.54392460366138209102e-03, +-2.47797874299740972931e-03, +-2.41144147109654920225e-03, +-2.34434599551184728525e-03, +-2.27672553377682423265e-03, +-2.20861329857108918892e-03, +-2.14004248299099744321e-03, +-2.07104624593109319652e-03, +-2.00165769758243626206e-03, +-1.93190988505322330110e-03, +-1.86183577811795423693e-03, +-1.79146825509988766485e-03, +-1.72084008889326943795e-03, +-1.64998393312966343087e-03, +-1.57893230849462818527e-03, +-1.50771758919912264932e-03, +-1.43637198961127387532e-03, +-1.36492755105304883201e-03, +-1.29341612876705033125e-03, +-1.22186937905778840625e-03, +-1.15031874661246304344e-03, +-1.07879545200534983015e-03, +-1.00733047939059738862e-03, +-9.35954564387392199190e-04, +-8.64698182161781326270e-04, +-7.93591535709335898878e-04, +-7.22664544342259342231e-04, +-6.51946832385152269008e-04, +-5.81467718082645003419e-04, +-5.11256202723101406751e-04, +-4.41340959980976682391e-04, +-3.71750325482115011495e-04, +-3.02512286594312090893e-04, +-2.33654472446860898751e-04, +-1.65204144181543805632e-04, +-9.71881854382950145007e-05, +-2.96330930778333087529e-05, + 3.74350318557888840534e-05, + 1.03990492930665522531e-04, + 1.70008006877860913661e-04, + 2.35462711895771908792e-04, + 3.00330175705594570618e-04, + 3.64586403356421419591e-04, + 4.28207844777551787079e-04, + 4.91171402077186748311e-04, + 5.53454436585029511952e-04, + 6.15034775638214118408e-04, + 6.75890719108685204992e-04, + 7.36001045671158494674e-04, + 7.95345018810736208159e-04, + 8.53902392568785988461e-04, + 9.11653417026953884206e-04, + 9.68578843528107927274e-04, + 1.02465992963409239201e-03, + 1.07987844381954517861e-03, + 1.13421666990184857697e-03, + 1.18765741120669863183e-03, + 1.24018399446962118877e-03, + 1.29178027347317181048e-03, + 1.34243063242041153760e-03, + 1.39211998904448393775e-03, + 1.44083379745542361494e-03, + 1.48855805072399061464e-03, + 1.53527928320389963832e-03, + 1.58098457259274222282e-03, + 1.62566154173287799080e-03, + 1.66929836015300469068e-03, + 1.71188374535185877309e-03, + 1.75340696382495094506e-03, + 1.79385783183615881223e-03, + 1.83322671593499951850e-03, + 1.87150453322187351919e-03, + 1.90868275136241117781e-03, + 1.94475338835288632730e-03, + 1.97970901203875114180e-03, + 2.01354273938795765367e-03, + 2.04624823552140497340e-03, + 2.07781971250251560127e-03, + 2.10825192788842950831e-03, + 2.13754018304492627786e-03, + 2.16568032122775241954e-03, + 2.19266872543273649843e-03, + 2.21850231601753312277e-03, + 2.24317854809751244041e-03, + 2.26669540871874157159e-03, + 2.28905141381085521987e-03, + 2.31024560492300908704e-03, + 2.33027754574556848419e-03, + 2.34914731842113299123e-03, + 2.36685551964774167771e-03, + 2.38340325657774047483e-03, + 2.39879214251553785076e-03, + 2.41302429241780800814e-03, + 2.42610231819949092105e-03, + 2.43802932384921434983e-03, + 2.44880890035772524199e-03, + 2.45844512046309356806e-03, + 2.46694253321619750424e-03, + 2.47430615837057783779e-03, + 2.48054148060029584083e-03, + 2.48565444354972896537e-03, + 2.48965144371932805070e-03, + 2.49253932419119233338e-03, + 2.49432536819870756192e-03, + 2.49501729254406187306e-03, + 2.49462324086802481049e-03, + 2.49315177677595679884e-03, + 2.49061187682437026880e-03, + 2.48701292337218105022e-03, + 2.48236469730101589823e-03, + 2.47667737060877201499e-03, + 2.46996149888082565729e-03, + 2.46222801364318543901e-03, + 2.45348821460201170497e-03, + 2.44375376177385136151e-03, + 2.43303666751100867299e-03, + 2.42134928842652587602e-03, + 2.40870431722312039469e-03, + 2.39511477443066006163e-03, + 2.38059400005651662299e-03, + 2.36515564515335941637e-03, + 2.34881366330883401689e-03, + 2.33158230206161314751e-03, + 2.31347609424828503169e-03, + 2.29450984928561332182e-03, + 2.27469864439260342423e-03, + 2.25405781575686164908e-03, + 2.23260294964972971082e-03, + 2.21034987349466626252e-03, + 2.18731464689328946802e-03, + 2.16351355261355186160e-03, + 2.13896308754443764677e-03, + 2.11367995362164717843e-03, + 2.08768104872860673846e-03, + 2.06098345757712827012e-03, + 2.03360444257223585765e-03, + 2.00556143466523338278e-03, + 1.97687202419953838434e-03, + 1.94755395175337346625e-03, + 1.91762509898370150235e-03, + 1.88710347947544372464e-03, + 1.85600722960030926380e-03, + 1.82435459938927956557e-03, + 1.79216394342290039413e-03, + 1.75945371174334418141e-03, + 1.72624244079242210488e-03, + 1.69254874437936271916e-03, + 1.65839130468247841071e-03, + 1.62378886328829906069e-03, + 1.58876021227249563002e-03, + 1.55332418532590395277e-03, + 1.51749964892962602506e-03, + 1.48130549358308134279e-03, + 1.44476062508820820261e-03, + 1.40788395589385340219e-03, + 1.37069439650360901800e-03, + 1.33321084695073701146e-03, + 1.29545218834344489506e-03, + 1.25743727448406820806e-03, + 1.21918492356532437090e-03, + 1.18071390994699786103e-03, + 1.14204295601606406994e-03, + 1.10319072413361980722e-03, + 1.06417580867146756643e-03, + 1.02501672814153568618e-03, + 9.85731917420752321024e-04, + 9.46339720074761028661e-04, + 9.06858380782653099826e-04, + 8.67306037865940180828e-04, + 8.27700715924154601863e-04, + 7.88060318579825755218e-04, + 7.48402621335140681366e-04, + 7.08745264542995573667e-04, + 6.69105746494616255432e-04, + 6.29501416626196083105e-04, + 5.89949468846577432593e-04, + 5.50466934988384673337e-04, + 5.11070678384569518186e-04, + 4.71777387572266644969e-04, + 4.32603570126133903009e-04, + 3.93565546622840108093e-04, + 3.54679444738640930936e-04, + 3.15961193481461178213e-04, + 2.77426517559644606348e-04, + 2.39090931888283949464e-04, + 2.00969736235134577339e-04, + 1.63078010007227617185e-04, + 1.25430607179671989044e-04, + 8.80421513676910678318e-05, + 5.09270310433270975443e-05, + 1.40993948977051206995e-05, +-2.24268526499689963992e-05, +-5.86380557959355767418e-05, +-9.45208115468090933828e-05, +-1.30061973765318488264e-04, +-1.65248657065980185041e-04, +-2.00068240560348736649e-04, +-2.34508371450769772170e-04, +-2.68556968472767403858e-04, +-3.02202225185153135114e-04, +-3.35432613107714699702e-04, +-3.68236884706315019053e-04, +-4.00604076224976460123e-04, +-4.32523510365022737217e-04, +-4.63984798811095579957e-04, +-4.94977844604242624843e-04, +-5.25492844361963827582e-04, +-5.55520290345540247376e-04, +-5.85050972374773735341e-04, +-6.14075979590610184985e-04, +-6.42586702065795259929e-04, +-6.70574832264203037069e-04, +-6.98032366349193725621e-04, +-7.24951605341828033552e-04, +-7.51325156129156322866e-04, +-7.77145932323820387393e-04, +-8.02407154975299293648e-04, +-8.27102353133903219450e-04, +-8.51225364268258727699e-04, +-8.74770334537431802288e-04, +-8.97731718918501797773e-04, +-9.20104281190827605862e-04, +-9.41883093778050233848e-04, +-9.63063537449165905750e-04, +-9.83641300879760935652e-04, +-1.00361238007481306557e-03, +-1.02297307765449128208e-03, +-1.04172000200423238610e-03, +-1.05985006629069969386e-03, +-1.07736048734502422482e-03, +-1.09424878441514257174e-03, +-1.11051277778848088776e-03, +-1.12615058728708443934e-03, +-1.14116063063659394818e-03, +-1.15554162171100749217e-03, +-1.16929256865495575027e-03, +-1.18241277188544584124e-03, +-1.19490182197486941203e-03, +-1.20675959741726535404e-03, +-1.21798626227982297217e-03, +-1.22858226374166065384e-03, +-1.23854832952187280184e-03, +-1.24788546519901061629e-03, +-1.25659495142406364872e-03, +-1.26467834102919943727e-03, +-1.27213745603428412742e-03, +-1.27897438455362244883e-03, +-1.28519147760499177768e-03, +-1.29079134582336268501e-03, +-1.29577685608154116216e-03, +-1.30015112802015094483e-03, +-1.30391753048923449490e-03, +-1.30707967790388737521e-03, +-1.30964142651636395419e-03, +-1.31160687060702277167e-03, +-1.31298033859659005196e-03, +-1.31376638908218385492e-03, +-1.31396980679961724973e-03, +-1.31359559851441281067e-03, +-1.31264898884408520024e-03, +-1.31113541601419526274e-03, +-1.30906052755070225271e-03, +-1.30643017591116055581e-03, +-1.30325041405731484843e-03, +-1.29952749097163636725e-03, +-1.29526784712039586857e-03, +-1.29047810986578645812e-03, +-1.28516508882973415524e-03, +-1.27933577121191956356e-03, +-1.27299731706460124078e-03, +-1.26615705452684046764e-03, +-1.25882247502064623448e-03, +-1.25100122841167137044e-03, +-1.24270111813698665680e-03, +-1.23393009630251375940e-03, +-1.22469625875265661526e-03, +-1.21500784011470538623e-03, +-1.20487320882053006339e-03, +-1.19430086210808427544e-03, +-1.18329942100529298017e-03, +-1.17187762529875026674e-03, +-1.16004432848981092231e-03, +-1.14780849274044756403e-03, +-1.13517918381147498753e-03, +-1.12216556599544479457e-03, +-1.10877689704675665670e-03, +-1.09502252311132830878e-03, +-1.08091187365826806380e-03, +-1.06645445641585442931e-03, +-1.05165985231426076241e-03, +-1.03653771043727446592e-03, +-1.02109774298538512859e-03, +-1.00534972025243104707e-03, +-9.89303465618205854493e-04, +-9.72968850559070386023e-04, +-9.56355789678956110487e-04, +-9.39474235762757228438e-04, +-9.22334174854466432199e-04, +-9.04945621361946477522e-04, +-8.87318613190598128385e-04, +-8.69463206907894578697e-04, +-8.51389472940857513876e-04, +-8.33107490808391681729e-04, +-8.14627344390523211622e-04, +-7.95959117236444131487e-04, +-7.77112887913182157074e-04, +-7.58098725396869001399e-04, +-7.38926684508335205812e-04, +-7.19606801394884719458e-04, +-7.00149089059903611230e-04, +-6.80563532942129469604e-04, +-6.60860086546161931871e-04, +-6.41048667125920334890e-04, +-6.21139151422514545521e-04, +-6.01141371458319205383e-04, +-5.81065110388481308873e-04, +-5.60920098411564179222e-04, +-5.40716008740645473485e-04, +-5.20462453636329636791e-04, +-5.00168980502928035153e-04, +-4.79845068049252442000e-04, +-4.59500122515179752151e-04, +-4.39143473965308969373e-04, +-4.18784372650737749064e-04, +-3.98431985440370181519e-04, +-3.78095392322528038760e-04, +-3.57783582978218623466e-04, +-3.37505453426840712917e-04, +-3.17269802745462131330e-04, +-2.97085329862539673351e-04, +-2.76960630426857884294e-04, +-2.56904193752789059696e-04, +-2.36924399842341755311e-04, +-2.17029516485020210204e-04, +-1.97227696436049984184e-04, +-1.77526974673721080374e-04, +-1.57935265736364822877e-04, +-1.38460361139671443579e-04, +-1.19109926874780676581e-04, +-9.98915009877096604120e-05, +-8.08124912404658787314e-05, +-6.18801728543761411219e-05, +-4.31016863358901726119e-05, +-2.44840353852607290751e-05, +-6.03408488822807525549e-06, + 1.22414410087942923482e-05, + 3.03359607401630166279e-05, + 4.82430370786643698930e-05, + 6.59563788094303331657e-05, + 8.34698423199615796228e-05, + 1.00777433106333784039e-04, + 1.17873307195481496850e-04, + 1.34751772483674884346e-04, + 1.51407289991337552218e-04, + 1.67834475034225882872e-04, + 1.84028098311239825778e-04, + 1.99983086909011169297e-04, + 2.15694525223608961004e-04, + 2.31157655799539194473e-04, + 2.46367880086458945071e-04, + 2.61320759113890506518e-04, + 2.76012014084471178285e-04, + 2.90437526885940853344e-04, + 3.04593340522622661477e-04, + 3.18475659466672001308e-04, + 3.32080849929764377465e-04, + 3.45405440055728798956e-04, + 3.58446120034815369788e-04, + 3.71199742140139986053e-04, + 3.83663320687053425832e-04, + 3.95834031916090828447e-04, + 4.07709213800306149479e-04, + 4.19286365777668133727e-04, + 4.30563148409382728376e-04, + 4.41537382964913725693e-04, + 4.52207050934656925797e-04, + 4.62570293470961546242e-04, + 4.72625410758635230730e-04, + 4.82370861315684551149e-04, + 4.91805261225328150740e-04, + 5.00927383300294468485e-04, + 5.09736156180340470138e-04, + 5.18230663364083014855e-04, + 5.26410142176160977465e-04, + 5.34273982670858136115e-04, + 5.41821726473215733132e-04, + 5.49053065558819199977e-04, + 5.55967840973343140065e-04, + 5.62566041493084596781e-04, + 5.68847802227587348751e-04, + 5.74813403165606124842e-04, + 5.80463267665585255090e-04, + 5.85797960891953992807e-04, + 5.90818188198352634011e-04, + 5.95524793459205619046e-04, + 5.99918757350793364382e-04, + 6.04001195583171897330e-04, + 6.07773357084216074402e-04, + 6.11236622137123529822e-04, + 6.14392500472671181100e-04, + 6.17242629317575641247e-04, + 6.19788771400296852575e-04, + 6.22032812915646266330e-04, + 6.23976761449542352556e-04, + 6.25622743865282679096e-04, + 6.26973004152734866845e-04, + 6.28029901241785953013e-04, + 6.28795906781460817864e-04, + 6.29273602886090081127e-04, + 6.29465679849935955126e-04, + 6.29374933831637162034e-04, + 6.29004264509917614644e-04, + 6.28356672711923979618e-04, + 6.27435258015602670238e-04, + 6.26243216327530610385e-04, + 6.24783837437580067548e-04, + 6.23060502551831571320e-04, + 6.21076681805128117189e-04, + 6.18835931754663313292e-04, + 6.16341892855999597296e-04, + 6.13598286922899423257e-04, + 6.10608914572360016171e-04, + 6.07377652656219848941e-04, + 6.03908451680720608987e-04, + 6.00205333215381750360e-04, + 5.96272387292547546150e-04, + 5.92113769798962869678e-04, + 5.87733699860716260477e-04, + 5.83136457222883410056e-04, + 5.78326379625196070923e-04, + 5.73307860175058681823e-04, + 5.68085344719199331932e-04, + 5.62663329215264671791e-04, + 5.57046357104629347515e-04, + 5.51239016687691835844e-04, + 5.45245938502918582949e-04, + 5.39071792710859535452e-04, + 5.32721286484389919269e-04, + 5.26199161406370888652e-04, + 5.19510190875949965511e-04, + 5.12659177524647379116e-04, + 5.05650950643461694588e-04, + 4.98490363622070692395e-04, + 4.91182291401325650700e-04, + 4.83731627940122419548e-04, + 4.76143283697776802978e-04, + 4.68422183132952726740e-04, + 4.60573262220249240485e-04, + 4.52601465985464203410e-04, + 4.44511746060588389465e-04, + 4.36309058259498746754e-04, + 4.27998360175392566791e-04, + 4.19584608800889610671e-04, + 4.11072758171783069880e-04, + 4.02467757035333936928e-04, + 3.93774546544049656484e-04, + 3.84998057975832470683e-04, + 3.76143210481313700240e-04, + 3.67214908859312392543e-04, + 3.58218041361136620669e-04, + 3.49157477524604336044e-04, + 3.40038066038525694287e-04, + 3.30864632638427479810e-04, + 3.21641978034209344382e-04, + 3.12374875870502510550e-04, + 3.03068070720368721877e-04, + 2.93726276113044930307e-04, + 2.84354172596324122988e-04, + 2.74956405834251703824e-04, + 2.65537584740686090270e-04, + 2.56102279649332684359e-04, + 2.46655020520732712157e-04, + 2.37200295186851598233e-04, + 2.27742547633623577692e-04, + 2.18286176322046336163e-04, + 2.08835532548216017655e-04, + 1.99394918842769620351e-04, + 1.89968587410093434423e-04, + 1.80560738607737464008e-04, + 1.71175519466368710516e-04, + 1.61817022250571095152e-04, + 1.52489283060860649410e-04, + 1.43196280477158617963e-04, + 1.33941934244020521144e-04, + 1.24730103997818122337e-04, + 1.15564588036148766046e-04, + 1.06449122129624024050e-04, + 9.73873783762444747338e-05, + 8.83829640984437603628e-05, + 7.94394207830501368397e-05, + 7.05602230641164422306e-05, + 6.17487777488439845697e-05, + 5.30084228865277819307e-05, + 4.43424268807018922721e-05, + 3.57539876443504868529e-05, + 2.72462317982963840894e-05, + 1.88222139126731892130e-05, + 1.04849157914673770899e-05, + 2.23724580001398245952e-06, +-5.91796176458841909860e-06, +-1.39779472603022615363e-05, +-2.19400262443108254274e-05, +-2.98015899747312779436e-05, +-3.75601058699388188874e-05, +-4.52131179258346812058e-05, +-5.27582470911579511194e-05, +-6.01931916011169823111e-05, +-6.75157272696155086192e-05, +-7.47237077402686759994e-05, +-8.18150646965978259242e-05, +-8.87878080315813176041e-05, +-9.56400259770174112402e-05, +-1.02369885192932295447e-04, +-1.08975630817447491838e-04, +-1.15455586477445233109e-04, +-1.21808154260462635915e-04, +-1.28031814648165977134e-04, +-1.34125126411867404445e-04, +-1.40086726470483718130e-04, +-1.45915329711446663599e-04, +-1.51609728774925367391e-04, +-1.57168793801964925671e-04, +-1.62591472146915872604e-04, +-1.67876788054762332352e-04, +-1.73023842303760092562e-04, +-1.78031811814023872061e-04, +-1.82899949222519527144e-04, +-1.87627582425063416539e-04, +-1.92214114085866635134e-04, +-1.96659021115234305434e-04, +-2.00961854115964548605e-04, +-2.05122236799067813760e-04, +-2.09139865369424642018e-04, +-2.13014507881963919287e-04, +-2.16746003569016719827e-04, +-2.20334262139455170628e-04, +-2.23779263050288623272e-04, +-2.27081054751326671731e-04, +-2.30239753903598189230e-04, +-2.33255544572162539776e-04, +-2.36128677394024743099e-04, +-2.38859468721759089912e-04, +-2.41448299743606627134e-04, +-2.43895615580664562507e-04, +-2.46201924361897988517e-04, +-2.48367796277648787261e-04, +-2.50393862612362249915e-04, +-2.52280814757210175570e-04, +-2.54029403203337271477e-04, +-2.55640436516424906718e-04, +-2.57114780293308988878e-04, +-2.58453356101321892260e-04, +-2.59657140401130335366e-04, +-2.60727163453730896234e-04, +-2.61664508212373382850e-04, +-2.62470309200077975623e-04, +-2.63145751373508769710e-04, +-2.63692068973905575490e-04, +-2.64110544365773612825e-04, +-2.64402506864084673854e-04, +-2.64569331550674807438e-04, +-2.64612438080565591254e-04, +-2.64533289478916812908e-04, +-2.64333390929326621406e-04, +-2.64014288554176887285e-04, +-2.63577568187730454374e-04, +-2.63024854142685936189e-04, +-2.62357807970878796362e-04, +-2.61578127218826830911e-04, +-2.60687544178804346540e-04, +-2.59687824636131118095e-04, +-2.58580766613355161020e-04, +-2.57368199111998000473e-04, +-2.56051980852535184582e-04, +-2.54633999013272917245e-04, +-2.53116167968770410229e-04, +-2.51500428028467203686e-04, +-2.49788744176148520739e-04, +-2.47983104810888498049e-04, +-2.46085520490098991209e-04, +-2.44098022675305284133e-04, +-2.42022662481256641692e-04, +-2.39861509428983846149e-04, +-2.37616650203396260988e-04, +-2.35290187416002671578e-04, +-2.32884238373345356290e-04, +-2.30400933851706944807e-04, +-2.27842416878660760553e-04, +-2.25210841522004905167e-04, +-2.22508371686640725982e-04, +-2.19737179919906623887e-04, +-2.16899446225907947382e-04, +-2.13997356889345798732e-04, +-2.11033103309352538255e-04, +-2.08008880843819519632e-04, +-2.04926887664708660573e-04, +-2.01789323624807442155e-04, +-1.98598389136399967663e-04, +-1.95356284062287273917e-04, +-1.92065206619610498147e-04, +-1.88727352296894345393e-04, +-1.85344912784731391314e-04, +-1.81920074920499755819e-04, +-1.78455019647530454055e-04, +-1.74951920989073971512e-04, +-1.71412945037461607323e-04, +-1.67840248958807175192e-04, +-1.64235980013589989322e-04, +-1.60602274593463965847e-04, +-1.56941257274607583660e-04, +-1.53255039887926981963e-04, +-1.49545720606400077326e-04, +-1.45815383049865629223e-04, +-1.42066095407511174204e-04, +-1.38299909578337953649e-04, +-1.34518860329830815736e-04, +-1.30724964475093245915e-04, +-1.26920220068654472992e-04, +-1.23106605621173758290e-04, +-1.19286079333219134950e-04, +-1.15460578348350841244e-04, +-1.11632018025632952099e-04, +-1.07802291231779830637e-04, +-1.03973267653065606659e-04, +-1.00146793127148565233e-04, +-9.63246889949230804435e-05, +-9.25087514725346873358e-05, +-8.87007510436452450671e-05, +-8.49024318720545515026e-05, +-8.11155112347393549661e-05, +-7.73416789754019609908e-05, +-7.35825969785674924512e-05, +-6.98398986642887023612e-05, +-6.61151885034750767074e-05, +-6.24100415538899748772e-05, +-5.87260030168200428450e-05, +-5.50645878143974986741e-05, +-5.14272801876128782695e-05, +-4.78155333149380714058e-05, +-4.42307689515766361233e-05, +-4.06743770892715146635e-05, +-3.71477156366324749162e-05, +-3.36521101199027279356e-05, +-3.01888534041130525139e-05, +-2.67592054345224943665e-05, +-2.33643929982665948157e-05, +-2.00056095060906951114e-05, +-1.66840147940797201324e-05, +-1.34007349452439661363e-05, +-1.01568621308437851693e-05, +-6.95345447128813701427e-06, +-3.79153591650250810366e-06, +-6.72096145553293655593e-07, + 2.40390951459279597616e-06, + 5.43556015137456058426e-06, + 8.42196931017640123499e-06, + 1.13622850193110927676e-05, + 1.42556897966238257746e-05, + 1.71014006379341248229e-05, + 1.98986689875390831126e-05, + 2.26467806909793172563e-05, + 2.53450559303131682314e-05, + 2.79928491421220740245e-05, + 3.05895489185053302676e-05, + 3.31345778912925430443e-05, + 3.56273925997451632237e-05, + 3.80674833419947510364e-05, + 4.04543740105068599521e-05, + 4.27876219118044463113e-05, + 4.50668175707753267513e-05, + 4.72915845198089502860e-05, + 4.94615790730713200283e-05, + 5.15764900862005805371e-05, + 5.36360387017334339240e-05, + 5.56399780805481871900e-05, + 5.75880931196438774090e-05, + 5.94802001565561985590e-05, + 6.13161466607366493955e-05, + 6.30958109121965409621e-05, + 6.48191016677504891876e-05, + 6.64859578151715343739e-05, + 6.80963480156043240521e-05, + 6.96502703345347587470e-05, + 7.11477518616810702089e-05, + 7.25888483201263885920e-05, + 7.39736436650163245096e-05, + 7.53022496721903708853e-05, + 7.65748055170595645635e-05, + 7.77914773440878826866e-05, + 7.89524578272120806021e-05, + 8.00579657215541123884e-05, + 8.11082454067584148567e-05, + 8.21035664223097817662e-05, + 8.30442229951717527346e-05, + 8.39305335600990616227e-05, + 8.47628402729624154692e-05, + 8.55415085174379832356e-05, + 8.62669264054029689666e-05, + 8.69395042713942022743e-05, + 8.75596741614536786501e-05, + 8.81278893167311284636e-05, + 8.86446236521661512422e-05, + 8.91103712306026604075e-05, + 8.95256457326717546962e-05, + 8.98909799227875892661e-05, + 9.02069251115862640782e-05, + 9.04740506151490363976e-05, + 9.06929432113401867103e-05, + 9.08642065935940279782e-05, + 9.09884608224771455898e-05, + 9.10663417753510066833e-05, + 9.10985005944656069544e-05, + 9.10856031337957275460e-05, + 9.10283294049456589850e-05, + 9.09273730224310103125e-05, + 9.07834406486567112131e-05, + 9.05972514388884682737e-05, + 9.03695364865346147717e-05, + 9.01010382690298824038e-05, + 8.97925100946232214449e-05, + 8.94447155503604388049e-05, + 8.90584279515538464710e-05, + 8.86344297930203114553e-05, + 8.81735122023717546660e-05, + 8.76764743956322256668e-05, + 8.71441231354561004216e-05, + 8.65772721922116491981e-05, + 8.59767418081955635050e-05, + 8.53433581652348287718e-05, + 8.46779528559294970011e-05, + 8.39813623587842351167e-05, + 8.32544275174723505482e-05, + 8.24979930244696123580e-05, + 8.17129069092911340059e-05, + 8.09000200315580515319e-05, + 8.00601855791177764851e-05, + 7.91942585714318722121e-05, + 7.83030953684469709260e-05, + 7.73875531851490379041e-05, + 7.64484896120066966278e-05, + 7.54867621414943666810e-05, + 7.45032277008856680736e-05, + 7.34987421914997258445e-05, + 7.24741600345781298914e-05, + 7.14303337239639759421e-05, + 7.03681133857495075701e-05, + 6.92883463450485250238e-05, + 6.81918767000556897513e-05, + 6.70795449035298084342e-05, + 6.59521873518545653477e-05, + 6.48106359818019012913e-05, + 6.36557178751403541801e-05, + 6.24882548712000070136e-05, + 6.13090631875229413088e-05, + 6.01189530487050480105e-05, + 5.89187283235398522627e-05, + 5.77091861705600261078e-05, + 5.64911166920768371556e-05, + 5.52653025968012133018e-05, + 5.40325188711331935503e-05, + 5.27935324591918643858e-05, + 5.15491019516612150597e-05, + 5.02999772835162253098e-05, + 4.90468994406823114189e-05, + 4.77906001756943685883e-05, + 4.65318017323872241855e-05, + 4.52712165796745444508e-05, + 4.40095471544385224527e-05, + 4.27474856135762158195e-05, + 4.14857135952114382585e-05, + 4.02249019891050019768e-05, + 3.89657107162695045101e-05, + 3.77087885178019617646e-05, + 3.64547727529321324196e-05, + 3.52042892062907349744e-05, + 3.39579519043854685862e-05, + 3.27163629412759540162e-05, + 3.14801123134230239524e-05, + 3.02497777637023744978e-05, + 2.90259246345387218443e-05, + 2.78091057301432964695e-05, + 2.65998611878025348972e-05, + 2.53987183581919854364e-05, + 2.42061916946511448772e-05, + 2.30227826513813061706e-05, + 2.18489795905047869758e-05, + 2.06852576979222047276e-05, + 1.95320789079097866306e-05, + 1.83898918363816234168e-05, + 1.72591317227478167385e-05, + 1.61402203802856600485e-05, + 1.50335661549492530784e-05, + 1.39395638925266073790e-05, + 1.28585949140593193966e-05, + 1.17910269994264146578e-05, + 1.07372143790027249535e-05, + 9.69749773328629209753e-06, + 8.67220420039572420566e-06, + 7.66164739132314657512e-06, + 6.66612741284622437347e-06, + 5.68593089796976951548e-06, + 4.72133104379410701050e-06, + 3.77258765668374723169e-06, + 2.83994720461857994069e-06, + 1.92364287659795633360e-06, + 1.02389464897677183691e-06, + 1.40909358598783243636e-07, +-7.25119217400925882488e-07, +-1.57401027526573751796e-06, +-2.40559589188401177682e-06, +-3.21972092580435969379e-06, +-4.01624291213239929447e-06, +-4.79503195145223449727e-06, +-5.55597059291959898474e-06, +-6.29895371166915398527e-06, +-7.02388838068995278969e-06, +-7.73069373730662337714e-06, +-8.41930084443043260571e-06, +-9.08965254672049638874e-06, +-9.74170332181420186798e-06, +-1.03754191267770145960e-05, +-1.09907772399306088372e-05, +-1.15877660982095854786e-05, +-1.21663851302071818753e-05, +-1.27266445850638015879e-05, +-1.32685653573596831328e-05, +-1.37921788081646564831e-05, +-1.42975265824070264185e-05, +-1.47846604227169150120e-05, +-1.52536419799077777845e-05, +-1.57045426202454864190e-05, +-1.61374432296745794440e-05, +-1.65524340151509907705e-05, +-1.69496143032443776877e-05, +-1.73290923361651281922e-05, +-1.76909850653765942752e-05, +-1.80354179429455134585e-05, +-1.83625247107888849940e-05, +-1.86724471879742999741e-05, +-1.89653350562250020523e-05, +-1.92413456437866339777e-05, +-1.95006437078064384194e-05, +-1.97434012153796016272e-05, +-1.99697971234102591856e-05, +-2.01800171574394671614e-05, +-2.03742535895865872536e-05, +-2.05527050157544749519e-05, +-2.07155761322383869926e-05, +-2.08630775118898238230e-05, +-2.09954253799722451970e-05, +-2.11128413898529763743e-05, +-2.12155523986690494219e-05, +-2.13037902431062623279e-05, +-2.13777915154254429865e-05, +-2.14377973398712400380e-05, +-2.14840531495946086989e-05, +-2.15168084642204138245e-05, +-2.15363166681862903517e-05, +-2.15428347899803886579e-05, +-2.15366232824005027408e-05, +-2.15179458039577262574e-05, +-2.14870690015422825217e-05, +-2.14442622944694083432e-05, +-2.13897976600211963056e-05, +-2.13239494205938423077e-05, +-2.12469940325636042692e-05, +-2.11592098769767039874e-05, +-2.10608770521689021838e-05, +-2.09522771684173563140e-05, +-2.08336931447246940868e-05, +-2.07054090078323760555e-05, +-2.05677096935581607638e-05, +-2.04208808505498906150e-05, +-2.02652086465450858026e-05, +-2.01009795772225878085e-05, +-1.99284802777307897448e-05, +-1.97479973369733553508e-05, +-1.95598171147313057406e-05, +-1.93642255616965921713e-05, +-1.91615080424908975211e-05, +-1.89519491617392180451e-05, +-1.87358325932659067312e-05, +-1.85134409124775290410e-05, +-1.82850554319945745078e-05, +-1.80509560405904254164e-05, +-1.78114210454942761765e-05, +-1.75667270181107023892e-05, +-1.73171486432067083623e-05, +-1.70629585716134836285e-05, +-1.68044272764881711800e-05, +-1.65418229131769521309e-05, +-1.62754111827191523261e-05, +-1.60054551990284544996e-05, +-1.57322153597849753270e-05, +-1.54559492210684566130e-05, +-1.51769113757617390406e-05, +-1.48953533357483810943e-05, +-1.46115234179280960335e-05, +-1.43256666340692667526e-05, +-1.40380245845161517285e-05, +-1.37488353557644599467e-05, +-1.34583334219182035850e-05, +-1.31667495500361276861e-05, +-1.28743107093750131593e-05, +-1.25812399845332226092e-05, +-1.22877564924967183814e-05, +-1.19940753035859587103e-05, +-1.17004073663007361519e-05, +-1.14069594360560160192e-05, +-1.11139340078022052344e-05, +-1.08215292525168970740e-05, +-1.05299389575568482923e-05, +-1.02393524708539662493e-05, +-9.94995464893742348120e-06, +-9.66192580876271611343e-06, +-9.37544168332491989210e-06, +-9.09067338103246418157e-06, +-8.80778734881422739372e-06, +-8.52694533893248795902e-06, +-8.24830437947059051977e-06, +-7.97201674846333152320e-06, +-7.69822995163491404110e-06, +-7.42708670370925303302e-06, +-7.15872491325360909230e-06, +-6.89327767101633304933e-06, +-6.63087324171573705124e-06, +-6.37163505923899323223e-06, +-6.11568172520321447157e-06, +-5.86312701083429459631e-06, +-5.61407986211404469277e-06, +-5.36864440814655013182e-06, +-5.12691997269171846217e-06, +-4.88900108881444233564e-06, +-4.65497751659457443244e-06, +-4.42493426384305196255e-06, +-4.19895160976678087265e-06, +-3.97710513152554464493e-06, +-3.75946573362158312445e-06, +-3.54609968006129461300e-06, +-3.33706862922910230812e-06, +-3.13242967141053148128e-06, +-2.93223536890220278037e-06, +-2.73653379864365903313e-06, +-2.54536859730841838172e-06, +-2.35877900878616331091e-06, +-2.17679993399191934131e-06, +-1.99946198293410626841e-06, +-1.82679152897453787459e-06, +-1.65881076521146377169e-06, +-1.49553776291791911430e-06, +-1.33698653196547020166e-06, +-1.18316708316432299485e-06, +-1.03408549244911473199e-06, +-8.89743966841013678409e-07, +-7.50140912114827378233e-07, +-6.15271002100918799020e-07, +-4.85125249549975873449e-07, +-3.59691078491283933177e-07, +-2.38952398011216803052e-07, +-1.22889677382464548894e-07, + 0 /* Need a final zero coefficient */ + diff --git a/libk3b/plugin/libsamplerate/float_cast.h b/libk3b/plugin/libsamplerate/float_cast.h new file mode 100644 index 0000000..af362e3 --- /dev/null +++ b/libk3b/plugin/libsamplerate/float_cast.h @@ -0,0 +1,203 @@ +/* +** Copyright (C) 2001-2003 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* Version 1.3 */ + + +/*============================================================================ +** On Intel Pentium processors (especially PIII and probably P4), converting +** from float to int is very slow. To meet the C specs, the code produced by +** most C compilers targeting Pentium needs to change the FPU rounding mode +** before the float to int conversion is performed. +** +** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It +** is this flushing of the pipeline which is so slow. +** +** Fortunately the ISO C99 specifications define the functions lrint, lrintf, +** llrint and llrintf which fix this problem as a side effect. +** +** On Unix-like systems, the configure process should have detected the +** presence of these functions. If they weren't found we have to replace them +** here with a standard C cast. +*/ + +/* +** The C99 prototypes for lrint and lrintf are as follows: +** +** long int lrintf (float x) ; +** long int lrint (double x) ; +*/ + +#include "config.h" + +/* +** The presence of the required functions are detected during the configure +** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in +** the config.h file. +*/ + +#define HAVE_LRINT_REPLACEMENT 0 + +#if (HAVE_LRINT && HAVE_LRINTF) + + /* + ** These defines enable functionality introduced with the 1999 ISO C + ** standard. They must be defined before the inclusion of math.h to + ** engage them. If optimization is enabled, these functions will be + ** inlined. With optimization switched off, you have to link in the + ** maths library using -lm. + */ + + #define _ISOC9X_SOURCE 1 + #define _ISOC99_SOURCE 1 + + #define __USE_ISOC9X 1 + #define __USE_ISOC99 1 + + #include + +#elif (defined (WIN32) || defined (_WIN32)) + + #undef HAVE_LRINT_REPLACEMENT + #define HAVE_LRINT_REPLACEMENT 1 + #include + + /* + ** Win32 doesn't seem to have these functions. + ** Therefore implement inline versions of these functions here. + */ + + __inline long int + lrint (double flt) + { int intgr; + + _asm + { fld flt + fistp intgr + } ; + + return intgr ; + } + + __inline long int + lrintf (float flt) + { int intgr; + + _asm + { fld flt + fistp intgr + } ; + + return intgr ; + } + +#elif (defined (__MWERKS__) && defined (macintosh)) + + /* This MacOS 9 solution was provided by Stephane Letz */ + + #undef HAVE_LRINT_REPLACEMENT + #define HAVE_LRINT_REPLACEMENT 1 + #include + + #undef lrint + #undef lrintf + + #define lrint double2int + #define lrintf float2int + + inline int + float2int (register float in) + { long res [2] ; + + asm + { fctiw in,in + stfd in,res + } + return res [1] ; + } /* float2int */ + + inline int + double2int (register double in) + { long res [2] ; + + asm + { fctiw in,in + stfd in,res + } + return res [1] ; + } /* double2int */ + +#elif (defined (__MACH__) && defined (__APPLE__)) + + /* For Apple MacOSX. */ + + #undef HAVE_LRINT_REPLACEMENT + #define HAVE_LRINT_REPLACEMENT 1 + #include + + #undef lrint + #undef lrintf + + #define lrint double2int + #define lrintf float2int + + inline static long int + float2int (register float in) + { int res [2] ; + + __asm__ __volatile__ + ( "fctiw %1, %1\n\t" + "stfd %1, %0" + : "=m" (res) /* Output */ + : "f" (in) /* Input */ + : "memory" + ) ; + + return res [1] ; + } /* lrintf */ + + inline static long int + double2int (register double in) + { int res [2] ; + + __asm__ __volatile__ + ( "fctiw %1, %1\n\t" + "stfd %1, %0" + : "=m" (res) /* Output */ + : "f" (in) /* Input */ + : "memory" + ) ; + + return res [1] ; + } /* lrint */ + +#else + #ifndef __sgi + #warning "Don't have the functions lrint() and lrintf()." + #warning "Replacing these functions with a standard C cast." + #endif + + #include + + #define lrint(dbl) ((int) (dbl)) + #define lrintf(flt) ((int) (flt)) + +#endif + + + diff --git a/libk3b/plugin/libsamplerate/high_qual_coeffs.h b/libk3b/plugin/libsamplerate/high_qual_coeffs.h new file mode 100644 index 0000000..229bc79 --- /dev/null +++ b/libk3b/plugin/libsamplerate/high_qual_coeffs.h @@ -0,0 +1,17116 @@ +/* +** Copyright (C) 2002,2003 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* +** f = make_filter (65, 128, 100.3) ; +** Pass band width : 0.0039062 (should be 0.0039062) +** Stop band atten. : 101.20 dB +** -3dB band width : 0.846 +** half length : 17087 +** increment : 128 +*/ + + 9.73822959712628111184e-01, + 9.73730227534126968614e-01, + 9.73452062795049033461e-01, + 9.72988560871685836950e-01, + 9.72339880681256651940e-01, + 9.71506244617024061760e-01, + 9.70487938457503807044e-01, + 9.69285311249795999977e-01, + 9.67898775167100988703e-01, + 9.66328805340476049146e-01, + 9.64575939664910952942e-01, + 9.62640778579811451365e-01, + 9.60523984823974497083e-01, + 9.58226283165186876190e-01, + 9.55748460104550945360e-01, + 9.53091363555660264772e-01, + 9.50255902498805649081e-01, + 9.47243046610318550904e-01, + 9.44053825867236739988e-01, + 9.40689330127495004774e-01, + 9.37150708685763667027e-01, + 9.33439169805209578712e-01, + 9.29555980225306610620e-01, + 9.25502464645995059911e-01, + 9.21280005188352291157e-01, + 9.16890040832049391106e-01, + 9.12334066829837087020e-01, + 9.07613634099317501125e-01, + 9.02730348592271192310e-01, + 8.97685870641828032035e-01, + 8.92481914287746591619e-01, + 8.87120246580144211634e-01, + 8.81602686861939210949e-01, + 8.75931106030353401337e-01, + 8.70107425777795429056e-01, + 8.64133617812459453589e-01, + 8.58011703058984220860e-01, + 8.51743750839512703266e-01, + 8.45331878035551986805e-01, + 8.38778248230970913113e-01, + 8.32085070836509732572e-01, + 8.25254600196225540643e-01, + 8.18289134676235541122e-01, + 8.11191015736170029093e-01, + 8.03962626983747541409e-01, + 7.96606393212902830214e-01, + 7.89124779425847022729e-01, + 7.81520289839554460620e-01, + 7.73795466877067239508e-01, + 7.65952890144075193568e-01, + 7.57995175391232733908e-01, + 7.49924973462656851986e-01, + 7.41744969231072803773e-01, + 7.33457880520075322650e-01, + 7.25066457013996301662e-01, + 7.16573479155810266761e-01, + 7.07981757033636860399e-01, + 6.99294129256251117965e-01, + 6.90513461818149987259e-01, + 6.81642646954653708136e-01, + 6.72684601987533770107e-01, + 6.63642268161698578588e-01, + 6.54518609473419998857e-01, + 6.45316611490632463521e-01, + 6.36039280165809350898e-01, + 6.26689640641951539735e-01, + 6.17270736052177193542e-01, + 6.07785626313482429950e-01, + 5.98237386915153934730e-01, + 5.88629107702400733437e-01, + 5.78963891655698170702e-01, + 5.69244853666411754212e-01, + 5.59475119309209012464e-01, + 5.49657823611788054485e-01, + 5.39796109822496594788e-01, + 5.29893128176318617406e-01, + 5.19952034659813655537e-01, + 5.09975989775514948477e-01, + 4.99968157306331650869e-01, + 4.89931703080488667457e-01, + 4.79869793737535021982e-01, + 4.69785595495954833023e-01, + 4.59682272922913082169e-01, + 4.49562987706663808041e-01, + 4.39430897432148248605e-01, + 4.29289154360313895964e-01, + 4.19140904211673437363e-01, + 4.08989284954621334922e-01, + 3.98837425599043837732e-01, + 3.88688444995713366925e-01, + 3.78545450641997294206e-01, + 3.68411537494394758507e-01, + 3.58289786788378861182e-01, + 3.48183264866087693878e-01, + 3.38095022012320112204e-01, + 3.28028091299366553191e-01, + 3.17985487441129255348e-01, + 3.07970205657046469661e-01, + 2.97985220546282070231e-01, + 2.88033484972657738421e-01, + 2.78117928960799731808e-01, + 2.68241458603957205753e-01, + 2.58406954983961600902e-01, + 2.48617273103761360353e-01, + 2.38875240832987723039e-01, + 2.29183657866993378827e-01, + 2.19545294699780346726e-01, + 2.09962891611264163005e-01, + 2.00439157669269424344e-01, + 1.90976769746686869667e-01, + 1.81578371554184297976e-01, + 1.72246572688870225321e-01, + 1.62983947699301107148e-01, + 1.53793035167208436143e-01, + 1.44676336806320998685e-01, + 1.35636316578646581865e-01, + 1.26675399828566487281e-01, + 1.17795972435093473929e-01, + 1.09000379982627515485e-01, + 1.00290926950544131979e-01, + 9.16698759219308212387e-02, + 8.31394468117901269677e-02, + 7.47018161150024284645e-02, + 6.63591161743508073378e-02, + 5.81134344688867474082e-02, + 4.99668129229093108123e-02, + 4.19212472358281990070e-02, + 3.39786862331567796058e-02, + 2.61410312388884458201e-02, + 1.84101354694814652035e-02, + 1.07878034496857889285e-02, + 3.27579045041895364904e-03, +-4.12419805110235924983e-03, +-1.14105068887806991584e-02, +-1.85815317024259456236e-02, +-2.56357194097392264431e-02, +-3.25715686553301464468e-02, +-3.93876302366183567161e-02, +-4.60825075064776670808e-02, +-5.26548567524927901840e-02, +-5.91033875527125010518e-02, +-6.54268631077873363822e-02, +-7.16241005493989252306e-02, +-7.76939712248916614090e-02, +-8.36354009580342477870e-02, +-8.94473702858456093390e-02, +-9.51289146714309197250e-02, +-1.00679124692788404816e-01, +-1.06097146207554629549e-01, +-1.11382180493666688159e-01, +-1.16533484365933040494e-01, +-1.21550370268516991223e-01, +-1.26432206343341957400e-01, +-1.31178416474445280748e-01, +-1.35788480308313530553e-01, +-1.40261933250244968940e-01, +-1.44598366436796466061e-01, +-1.48797426684381700612e-01, +-1.52858816414098541703e-01, +-1.56782293552872986631e-01, +-1.60567671411021850592e-01, +-1.64214818536340179111e-01, +-1.67723658544838616358e-01, +-1.71094169928257461288e-01, +-1.74326385838498049141e-01, +-1.77420393849128360531e-01, +-1.80376335694119815933e-01, +-1.83194406983985758064e-01, +-1.85874856899509832697e-01, +-1.88417987863249564162e-01, +-1.90824155189017602430e-01, +-1.93093766709557357331e-01, +-1.95227282382623990031e-01, +-1.97225213875713484279e-01, +-1.99088124129663118778e-01, +-2.00816626901390404836e-01, +-2.02411386286012268121e-01, +-2.03873116218622224549e-01, +-2.05202579955993086314e-01, +-2.06400589538496825881e-01, +-2.07468005232528396320e-01, +-2.08405734953734406156e-01, +-2.09214733671363894985e-01, +-2.09896002794046132589e-01, +-2.10450589537331811396e-01, +-2.10879586273321456558e-01, +-2.11184129862729524918e-01, +-2.11365400969725530933e-01, +-2.11424623359909302778e-01, +-2.11363063181782606659e-01, +-2.11182028232088397912e-01, +-2.10882867205385543530e-01, +-2.10466968928249342774e-01, +-2.09935761578479540557e-01, +-2.09290711889717429006e-01, +-2.08533324341858283812e-01, +-2.07665140337684211991e-01, +-2.06687737366111012882e-01, +-2.05602728152473046563e-01, +-2.04411759796272074485e-01, +-2.03116512896803713684e-01, +-2.01718700667107064817e-01, +-2.00220068036660509003e-01, +-1.98622390743273286029e-01, +-1.96927474414606312747e-01, +-1.95137153639780930314e-01, +-1.93253291031515200826e-01, +-1.91277776279251604530e-01, +-1.89212525193726166517e-01, +-1.87059478743444584925e-01, +-1.84820602083524743176e-01, +-1.82497883577372205233e-01, +-1.80093333811659150889e-01, +-1.77608984605069908369e-01, +-1.75046888011289869524e-01, +-1.72409115316711214483e-01, +-1.69697756033324376190e-01, +-1.66914916887274944468e-01, +-1.64062720803562822613e-01, +-1.61143305887356008688e-01, +-1.58158824402401171350e-01, +-1.55111441747006084668e-01, +-1.52003335428069458191e-01, +-1.48836694033641553370e-01, +-1.45613716204482351868e-01, +-1.42336609605105829379e-01, +-1.39007589894771910188e-01, +-1.35628879698910465024e-01, +-1.32202707581443923424e-01, +-1.28731307018481316851e-01, +-1.25216915373852127891e-01, +-1.21661772876947515964e-01, +-1.18068121603333617275e-01, +-1.14438204458597023172e-01, +-1.10774264165883040700e-01, +-1.07078542257586659114e-01, +-1.03353278071642365465e-01, +-9.96007077528702211566e-02, +-9.58230632598184722815e-02, +-9.20225713775505993475e-02, +-8.82014527368129436224e-02, +-8.43619208400154807492e-02, +-8.05061810944624617337e-02, +-7.66364298532504761852e-02, +-7.27548534642616651080e-02, +-6.88636273276640731300e-02, +-6.49649149623320182334e-02, +-6.10608670815911136476e-02, +-5.71536206786884617981e-02, +-5.32452981223815041689e-02, +-4.93380062630371721277e-02, +-4.54338355496189602589e-02, +-4.15348591579423748188e-02, +-3.76431321305677607514e-02, +-3.37606905286930644716e-02, +-2.98895505964036217739e-02, +-2.60317079376298707305e-02, +-2.21891367061550388862e-02, +-1.83637888090092127324e-02, +-1.45575931235783270074e-02, +-1.07724547287478406021e-02, +-7.01025415039811198442e-03, +-3.27284662155273445641e-03, + 4.37938642517908310794e-04, + 4.12029915395035594566e-03, + 7.77245984641533344678e-03, + 1.13926737534469080249e-02, + 1.49792226707046640527e-02, + 1.85304178019153227563e-02, + 2.20446003882424183817e-02, + 2.55201423208448671676e-02, + 2.89554467363942642788e-02, + 3.23489485953257979722e-02, + 3.56991152426125377128e-02, + 3.90044469508545738057e-02, + 4.22634774454904785235e-02, + 4.54747744119432459331e-02, + 4.86369399845229810619e-02, + 5.17486112169195516808e-02, + 5.48084605341252126265e-02, + 5.78151961656372809228e-02, + 6.07675625598040544673e-02, + 6.36643407791787629968e-02, + 6.65043488767638746317e-02, + 6.92864422530337364936e-02, + 7.20095139936314521112e-02, + 7.46724951876515663507e-02, + 7.72743552264206767788e-02, + 7.98141020827076302924e-02, + 8.22907825702981904348e-02, + 8.47034825838767768680e-02, + 8.70513273191783898408e-02, + 8.93334814733681981114e-02, + 9.15491494256309712441e-02, + 9.36975753979484987655e-02, + 9.57780435960658566019e-02, + 9.77898783306437036078e-02, + 9.97324441186170501661e-02, + 1.01605145764776208517e-01, + 1.03407428423609545898e-01, + 1.05138777641444206012e-01, + 1.06798719378940032421e-01, + 1.08386820013995285872e-01, + 1.09902686325133475131e-01, + 1.11345965455456150095e-01, + 1.12716344857240108324e-01, + 1.14013552217288011148e-01, + 1.15237355363129817531e-01, + 1.16387562150195578159e-01, + 1.17464020330083573906e-01, + 1.18466617400054957665e-01, + 1.19395280433899547701e-01, + 1.20249975894323096748e-01, + 1.21030709427012495016e-01, + 1.21737525636550936170e-01, + 1.22370507844354617366e-01, + 1.22929777828819461472e-01, + 1.23415495547866391202e-01, + 1.23827858844088756207e-01, + 1.24167103132708178670e-01, + 1.24433501072553173716e-01, + 1.24627362220290069383e-01, + 1.24749032668130088730e-01, + 1.24798894665256510095e-01, + 1.24777366223214461471e-01, + 1.24684900705517007213e-01, + 1.24521986401729317651e-01, + 1.24289146086293156301e-01, + 1.23986936562369309822e-01, + 1.23615948190973698462e-01, + 1.23176804405697795652e-01, + 1.22670161213299697134e-01, + 1.22096706680470845630e-01, + 1.21457160407075034914e-01, + 1.20752272986177383585e-01, + 1.19982825451170740938e-01, + 1.19149628710327484815e-01, + 1.18253522969096608319e-01, + 1.17295377140480550082e-01, + 1.16276088243826986046e-01, + 1.15196580792372674229e-01, + 1.14057806169890793568e-01, + 1.12860741996784086361e-01, + 1.11606391485979145051e-01, + 1.10295782788982596467e-01, + 1.08929968332454704671e-01, + 1.07510024145666946427e-01, + 1.06037049179214082351e-01, + 1.04512164615345154450e-01, + 1.02936513170294341446e-01, + 1.01311258388983055356e-01, + 9.96375839324763756810e-02, + 9.79166928585712137423e-02, + 9.61498068959035084857e-02, + 9.43381657119597566430e-02, + 9.24830261753778609668e-02, + 9.05856616129300240559e-02, + 8.86473610615743090602e-02, + 8.66694285159709948418e-02, + 8.46531821718525673282e-02, + 8.25999536656427529868e-02, + 8.05110873107188207420e-02, + 7.83879393307109761935e-02, + 7.62318770902338793682e-02, + 7.40442783234440127238e-02, + 7.18265303608213723230e-02, + 6.95800293545625059277e-02, + 6.73061795029863685347e-02, + 6.50063922743394223547e-02, + 6.26820856303954981881e-02, + 6.03346832502406754672e-02, + 5.79656137546301838959e-02, + 5.55763099313076533448e-02, + 5.31682079616711544823e-02, + 5.07427466491714163066e-02, + 4.83013666498223193102e-02, + 4.58455097052048524131e-02, + 4.33766178783417805098e-02, + 4.08961327928156204159e-02, + 3.84054948755038344510e-02, + 3.59061426032981009793e-02, + 3.33995117541749445000e-02, + 3.08870346629779371495e-02, + 2.83701394822698481357e-02, + 2.58502494486117818939e-02, + 2.33287821546176998844e-02, + 2.08071488271321346220e-02, + 1.82867536118745781237e-02, + 1.57689928648852076276e-02, + 1.32552544511122961240e-02, + 1.07469170504618516393e-02, + 8.24534947164058847069e-03, + 5.75190997410870291651e-03, + 3.26794559845353929303e-03, + 7.94791505500461897306e-04, +-1.66622967554532603295e-03, +-4.11380848962069559788e-03, +-6.54664928870115660209e-03, +-8.96347085478857441565e-03, +-1.13630070127026094190e-02, +-1.37440072324107598334e-02, +-1.61052372206219249207e-02, +-1.84454795013846463425e-02, +-2.07635339854373018875e-02, +-2.30582185280550702733e-02, +-2.53283694751598974226e-02, +-2.75728421974516593740e-02, +-2.97905116123358577884e-02, +-3.19802726934248146562e-02, +-3.41410409673992970570e-02, +-3.62717529980220235175e-02, +-3.83713668571045649069e-02, +-4.04388625822339128901e-02, +-4.24732426210736174754e-02, +-4.44735322620624928813e-02, +-4.64387800513385851087e-02, +-4.83680581957297989204e-02, +-5.02604629516505974074e-02, +-5.21151149997620341536e-02, +-5.39311598052534396652e-02, +-5.57077679636137287900e-02, +-5.74441355317703919448e-02, +-5.91394843444778550712e-02, +-6.07930623158483146584e-02, +-6.24041437259244130553e-02, +-6.39720294922026394557e-02, +-6.54960474260223579623e-02, +-6.69755524737441765293e-02, +-6.84099269426502037961e-02, +-6.97985807115074213813e-02, +-7.11409514257386743630e-02, +-7.24365046771608261933e-02, +-7.36847341682554390907e-02, +-7.48851618609372993163e-02, +-7.60373381098108092058e-02, +-7.71408417798946782762e-02, +-7.81952803488157183187e-02, +-7.92002899934755172362e-02, +-8.01555356612003028216e-02, +-8.10607111253977136167e-02, +-8.19155390257452209468e-02, +-8.27197708929510444609e-02, +-8.34731871581248646708e-02, +-8.41755971468178959549e-02, +-8.48268390577856662427e-02, +-8.54267799265437804968e-02, +-8.59753155737910251810e-02, +-8.64723705387828583957e-02, +-8.69178979977427990100e-02, +-8.73118796674136471436e-02, +-8.76543256938471931905e-02, +-8.79452745265522362050e-02, +-8.81847927781117119084e-02, +-8.83729750694022264668e-02, +-8.85099438605464611252e-02, +-8.85958492677388215197e-02, +-8.86308688660923243985e-02, +-8.86152074786611815282e-02, +-8.85490969517982173809e-02, +-8.84327959170169153325e-02, +-8.82665895395295801995e-02, +-8.80507892536431108210e-02, +-8.77857324851982756542e-02, +-8.74717823612454203897e-02, +-8.71093274071546297410e-02, +-8.66987812313650407781e-02, +-8.62405821979837367008e-02, +-8.57351930874506312774e-02, +-8.51831007454873639917e-02, +-8.45848157205629364030e-02, +-8.39408718901024919479e-02, +-8.32518260756789918453e-02, +-8.25182576474303292047e-02, +-8.17407681179471573563e-02, +-8.09199807258840636548e-02, +-8.00565400095505641520e-02, +-7.91511113707415864260e-02, +-7.82043806290729365260e-02, +-7.72170535670915342275e-02, +-7.61898554664313942819e-02, +-7.51235306352922710404e-02, +-7.40188419275257664109e-02, +-7.28765702536047221827e-02, +-7.16975140837712299202e-02, +-7.04824889436477669546e-02, +-6.92323269026086512978e-02, +-6.79478760552057331479e-02, +-6.66299999959486799472e-02, +-6.52795772877406560442e-02, +-6.38975009242730290770e-02, +-6.24846777866859409700e-02, +-6.10420280948025528733e-02, +-5.95704848532464525945e-02, +-5.80709932927548425075e-02, +-5.65445103069988283528e-02, +-5.49920038852278469932e-02, +-5.34144525410520376596e-02, +-5.18128447376807535485e-02, +-5.01881783099329334408e-02, +-4.85414598833405000478e-02, +-4.68737042906593598390e-02, +-4.51859339861135078653e-02, +-4.34791784576844600463e-02, +-4.17544736377706837693e-02, +-4.00128613125346824231e-02, +-3.82553885302546123337e-02, +-3.64831070090038678266e-02, +-3.46970725439699687054e-02, +-3.28983444147356932086e-02, +-3.10879847928346199348e-02, +-2.92670581498969371859e-02, +-2.74366306667012324616e-02, +-2.55977696434401616465e-02, +-2.37515429115148085648e-02, +-2.18990182471639621697e-02, +-2.00412627872342125057e-02, +-1.81793424474003748048e-02, +-1.63143213431318143125e-02, +-1.44472612137104394064e-02, +-1.25792208495948080321e-02, +-1.07112555234262843418e-02, +-8.84441642496919776251e-03, +-6.97975010027273440327e-03, +-5.11829789534247545785e-03, +-3.26109540460238272672e-03, +-1.40917192442717876394e-03, + 4.36450087979504280662e-04, + 2.27475555008947467189e-03, + 4.10473728366783034011e-03, + 5.92539653824247346953e-03, + 7.73574350816149444027e-03, + 9.53479784298774321605e-03, + 1.13215891509725555958e-02, + 1.30951574953684958535e-02, + 1.48545538833333903156e-02, + 1.65988407471903930135e-02, + 1.83270924178097725787e-02, + 2.00383955898867233136e-02, + 2.17318497788877018628e-02, + 2.34065677694524146291e-02, + 2.50616760550354221448e-02, + 2.66963152685791259289e-02, + 2.83096406040205736399e-02, + 2.99008222284305145988e-02, + 3.14690456845965957355e-02, + 3.30135122838646696830e-02, + 3.45334394890581680704e-02, + 3.60280612873039099431e-02, + 3.74966285525929615696e-02, + 3.89384093979178655398e-02, + 4.03526895168305685391e-02, + 4.17387725142676843659e-02, + 4.30959802265037661417e-02, + 4.44236530300948923022e-02, + 4.57211501396783959184e-02, + 4.69878498945072997639e-02, + 4.82231500336007049001e-02, + 4.94264679593977643290e-02, + 5.05972409898094652170e-02, + 5.17349265985714082405e-02, + 5.28390026438036938816e-02, + 5.39089675846917554258e-02, + 5.49443406862122687984e-02, + 5.59446622118279432434e-02, + 5.69094936040880627903e-02, + 5.78384176530744725797e-02, + 5.87310386526413361064e-02, + 5.95869825444026307570e-02, + 6.04058970494284683261e-02, + 6.11874517876177664855e-02, + 6.19313383847234916191e-02, + 6.26372705670065754724e-02, + 6.33049842435138704344e-02, + 6.39342375759682501890e-02, + 6.45248110362744708990e-02, + 6.50765074516480857003e-02, + 6.55891520373845793301e-02, + 6.60625924172834749770e-02, + 6.64966986317623437452e-02, + 6.68913631336883612866e-02, + 6.72465007719728613544e-02, + 6.75620487629735172463e-02, + 6.78379666497569006056e-02, + 6.80742362492841729393e-02, + 6.82708615875821517305e-02, + 6.84278688229765230666e-02, + 6.85453061574607669382e-02, + 6.86232437362914587942e-02, + 6.86617735358941577717e-02, + 6.86610092401827576403e-02, + 6.86210861053920678776e-02, + 6.85421608135311638543e-02, + 6.84244113145758836581e-02, + 6.82680366575164482290e-02, + 6.80732568103898511014e-02, + 6.78403124694252068760e-02, + 6.75694648574412526365e-02, + 6.72609955116377500328e-02, + 6.69152060609276150283e-02, + 6.65324179929640407982e-02, + 6.61129724110185862385e-02, + 6.56572297808763333249e-02, + 6.51655696679120516324e-02, + 6.46383904645234791397e-02, + 6.40761091080973010925e-02, + 6.34791607896909026998e-02, + 6.28479986536143592213e-02, + 6.21830934881068692066e-02, + 6.14849334072996994704e-02, + 6.07540235246672929992e-02, + 5.99908856181665117724e-02, + 5.91960577872764140417e-02, + 5.83700941021449495882e-02, + 5.75135642450580880647e-02, + 5.66270531444532515541e-02, + 5.57111606016933366692e-02, + 5.47665009108296851892e-02, + 5.37937024715815850784e-02, + 5.27934073957626870399e-02, + 5.17662711073889059143e-02, + 5.07129619367031950206e-02, + 4.96341607083598743144e-02, + 4.85305603240058919257e-02, + 4.74028653395071053467e-02, + 4.62517915370636301109e-02, + 4.50780654924642990022e-02, + 4.38824241377281029641e-02, + 4.26656143193894568655e-02, + 4.14283923526756400757e-02, + 4.01715235718370783369e-02, + 3.88957818768817381594e-02, + 3.76019492769772492591e-02, + 3.62908154307766822599e-02, + 3.49631771839265942381e-02, + 3.36198381040227756156e-02, + 3.22616080132712215733e-02, + 3.08893025191169512400e-02, + 2.95037425431055044811e-02, + 2.81057538482372380739e-02, + 2.66961665650768086022e-02, + 2.52758147168840839603e-02, + 2.38455357440239580635e-02, + 2.24061700279218310727e-02, + 2.09585604148223095256e-02, + 1.95035517396166743764e-02, + 1.80419903499945237513e-02, + 1.65747236311830255240e-02, + 1.51025995315297069388e-02, + 1.36264660891878813115e-02, + 1.21471709601575494908e-02, + 1.06655609479410495855e-02, + 9.18248153506075540098e-03, + 7.69877641669523653245e-03, + 6.21528703667832953944e-03, + 4.73285212611389023013e-03, + 3.25230724484593071086e-03, + 1.77448432603104764606e-03, + 3.00211224053546050453e-04, +-1.16968873398075085164e-03, +-2.63439719293501574751e-03, +-4.09310121028114842767e-03, +-5.54499369246326881400e-03, +-6.98927382675401144552e-03, +-8.42514750838012187184e-03, +-9.85182776269834421801e-03, +-1.12685351622023224166e-02, +-1.26744982381468297011e-02, +-1.40689538865774264181e-02, +-1.54511477685608713400e-02, +-1.68203347044119586040e-02, +-1.81757790617144907031e-02, +-1.95167551369457396848e-02, +-2.08425475305089903666e-02, +-2.21524515149872230912e-02, +-2.34457733964363347623e-02, +-2.47218308685369890509e-02, +-2.59799533594318662888e-02, +-2.72194823710760064328e-02, +-2.84397718109379513129e-02, +-2.96401883158870678436e-02, +-3.08201115681125577261e-02, +-3.19789346029227747326e-02, +-3.31160641082781370681e-02, +-3.42309207159130005071e-02, +-3.53229392839145145411e-02, +-3.63915691706218277779e-02, +-3.74362744997228866217e-02, +-3.84565344164232020274e-02, +-3.94518433345735566875e-02, +-4.04217111746440760367e-02, +-4.13656635924379983971e-02, +-4.22832421984465703368e-02, +-4.31740047677477145616e-02, +-4.40375254403603463849e-02, +-4.48733949119690250784e-02, +-4.56812206149411689782e-02, +-4.64606268895620885817e-02, +-4.72112551454219875335e-02, +-4.79327640128901638628e-02, +-4.86248294846227807620e-02, +-4.92871450470508051800e-02, +-4.99194218018040730689e-02, +-5.05213885770312357004e-02, +-5.10927920285815725943e-02, +-5.16333967310192848421e-02, +-5.21429852584503056301e-02, +-5.26213582551397357490e-02, +-5.30683344959132635710e-02, +-5.34837509363331325973e-02, +-5.38674627526497529217e-02, +-5.42193433715342787416e-02, +-5.45392844896020398404e-02, +-5.48271960827455065446e-02, +-5.50830064052948084607e-02, +-5.53066619790379757071e-02, +-5.54981275721307884541e-02, +-5.56573861679344195075e-02, +-5.57844389238277491017e-02, +-5.58793051200398085965e-02, +-5.59420220985603691699e-02, +-5.59726451921854703531e-02, +-5.59712476437655773176e-02, +-5.59379205157255615655e-02, +-5.58727725899317365088e-02, +-5.57759302579874938210e-02, +-5.56475374020423893540e-02, +-5.54877552662062720201e-02, +-5.52967623186622694864e-02, +-5.50747541045816801919e-02, +-5.48219430899443069261e-02, +-5.45385584963738595521e-02, +-5.42248461271042508924e-02, +-5.38810681841958433180e-02, +-5.35075030771247142636e-02, +-5.31044452228734698007e-02, +-5.26722048376558060756e-02, +-5.22111077204129997442e-02, +-5.17214950282209942611e-02, +-5.12037230437547910555e-02, +-5.06581629349584436350e-02, +-5.00852005070748507176e-02, +-4.94852359471897595977e-02, +-4.88586835614527661975e-02, +-4.82059715051387852047e-02, +-4.75275415057165098731e-02, +-4.68238485790967787215e-02, +-4.60953607392339606563e-02, +-4.53425587012589517699e-02, +-4.45659355783224117586e-02, +-4.37659965723364227652e-02, +-4.29432586587956896529e-02, +-4.20982502658717866462e-02, +-4.12315109479716793150e-02, +-4.03435910539542696984e-02, +-3.94350513902031810098e-02, +-3.85064628787541649024e-02, +-3.75584062106811000792e-02, +-3.65914714949422334445e-02, +-3.56062579028932485459e-02, +-3.46033733086755293518e-02, +-3.35834339256887229319e-02, +-3.25470639393581201437e-02, +-3.14948951364113841067e-02, +-3.04275665308768074324e-02, +-2.93457239870188353603e-02, +-2.82500198394295444493e-02, +-2.71411125104896906735e-02, +-2.60196661254226829785e-02, +-2.48863501251557692195e-02, +-2.37418388772132477049e-02, +-2.25868112848582602847e-02, +-2.14219503947065334493e-02, +-2.02479430030328977352e-02, +-1.90654792609915822721e-02, +-1.78752522789717531448e-02, +-1.66779577303104824260e-02, +-1.54742934545847657390e-02, +-1.42649590607015902544e-02, +-1.30506555300084672172e-02, +-1.18320848196448689948e-02, +-1.06099494663520910881e-02, +-9.38495219096077346044e-03, +-8.15779550377599728395e-03, +-6.92918131107302364552e-03, +-5.69981052292132129439e-03, +-4.47038266255170985142e-03, +-3.24159547747867194528e-03, +-2.01414455258872894527e-03, +-7.88722925405390719311e-04, + 4.33979296259515102616e-04, + 1.65327531406484059748e-03, + 2.86848201610344138643e-03, + 4.07892035086573293695e-03, + 5.28391569800646006272e-03, + 6.48279823571479112132e-03, + 7.67490330449144362440e-03, + 8.85957176714050748112e-03, + 1.00361503647855877797e-02, + 1.12039920687220222878e-02, + 1.23624564279179102733e-02, + 1.35109099119845744302e-02, + 1.46487262494354297110e-02, + 1.57752867610552773014e-02, + 1.68899806882093564409e-02, + 1.79922055159205465658e-02, + 1.90813672905472929420e-02, + 2.01568809318992299418e-02, + 2.12181705396309386313e-02, + 2.22646696937574897768e-02, + 2.32958217491361675722e-02, + 2.43110801237692714105e-02, + 2.53099085807794131620e-02, + 2.62917815039164816382e-02, + 2.72561841664596578305e-02, + 2.82026129933784439063e-02, + 2.91305758166261995201e-02, + 3.00395921234366258812e-02, + 3.09291932975059961908e-02, + 3.17989228529399620138e-02, + 3.26483366608550443222e-02, + 3.34770031685240748720e-02, + 3.42845036109633918842e-02, + 3.50704322148587890884e-02, + 3.58343963947392735170e-02, + 3.65760169413035240993e-02, + 3.72949282018151320739e-02, + 3.79907782524846540650e-02, + 3.86632290627611160949e-02, + 3.93119566514606166852e-02, + 3.99366512346636878816e-02, + 4.05370173653198731523e-02, + 4.11127740644999239983e-02, + 4.16636549442422551848e-02, + 4.21894083219462659451e-02, + 4.26897973262660088145e-02, + 4.31645999944682140503e-02, + 4.36136093612174424727e-02, + 4.40366335387612217733e-02, + 4.44334957884889164559e-02, + 4.48040345838451384286e-02, + 4.51481036645831335097e-02, + 4.54655720823471248826e-02, + 4.57563242375793044481e-02, + 4.60202599077495430602e-02, + 4.62572942669144740457e-02, + 4.64673578966120978673e-02, + 4.66503967881086306635e-02, + 4.68063723360144789964e-02, + 4.69352613232939530619e-02, + 4.70370558976949404428e-02, + 4.71117635396342340770e-02, + 4.71594070215737987128e-02, + 4.71800243589305737246e-02, + 4.71736687525673714649e-02, + 4.71404085229153516079e-02, + 4.70803270357842834626e-02, + 4.69935226199208050391e-02, + 4.68801084763797309973e-02, + 4.67402125797770004456e-02, + 4.65739775714988368804e-02, + 4.63815606449435313685e-02, + 4.61631334228796152974e-02, + 4.59188818270049037285e-02, + 4.56490059397985786793e-02, + 4.53537198587595224986e-02, + 4.50332515431300858810e-02, + 4.46878426532076045152e-02, + 4.43177483823498988280e-02, + 4.39232372817854738178e-02, + 4.35045910783411482470e-02, + 4.30621044852065107400e-02, + 4.25960850058553150421e-02, + 4.21068527312480900271e-02, + 4.15947401304457009541e-02, + 4.10600918347645213458e-02, + 4.05032644156081075848e-02, + 3.99246261561139251239e-02, + 3.93245568167555487049e-02, + 3.87034473950466154091e-02, + 3.80616998794914215831e-02, + 3.73997269979330568268e-02, + 3.67179519604542980993e-02, + 3.60168081969824901978e-02, + 3.52967390897612337541e-02, + 3.45581977008463520074e-02, + 3.38016464947914485606e-02, + 3.30275570566867723854e-02, + 3.22364098057202272396e-02, + 3.14286937044311875944e-02, + 3.06049059638265272265e-02, + 2.97655517445348863359e-02, + 2.89111438541742558905e-02, + 2.80422024411093630258e-02, + 2.71592546847793693543e-02, + 2.62628344827749958534e-02, + 2.53534821348480460257e-02, + 2.44317440240356988090e-02, + 2.34981722950843643916e-02, + 2.25533245303600957121e-02, + 2.15977634234290963300e-02, + 2.06320564504986307675e-02, + 1.96567755399048478548e-02, + 1.86724967398384719686e-02, + 1.76797998844943696217e-02, + 1.66792682588392839060e-02, + 1.56714882621848752842e-02, + 1.46570490707573775069e-02, + 1.36365422994567421500e-02, + 1.26105616629926826217e-02, + 1.15797026365911225748e-02, + 1.05445621164599462327e-02, + 9.50573808020578961409e-03, + 8.46382924739110323320e-03, + 7.41943474041982693745e-03, + 6.37315374594339158210e-03, + 5.32558517697237672472e-03, + 4.27732733588230377986e-03, + 3.22897757850148679412e-03, + 2.18113197946379544154e-03, + 1.13438499901297824499e-03, + 8.93291514401199637785e-05, +-9.53445324662180308285e-04, +-1.99335079414908163467e-03, +-3.02980255089889101774e-03, +-4.06221914103327592926e-03, +-5.09002268361045690642e-03, +-6.11263918861550906853e-03, +-7.12949887207463706834e-03, +-8.14003646812562139945e-03, +-9.14369153787539246103e-03, +-1.01399087748766797423e-02, +-1.11281383070643315192e-02, +-1.21078359949849043153e-02, +-1.30784637261652115364e-02, +-1.40394897054589556235e-02, +-1.49903887412209321783e-02, +-1.59306425271560810064e-02, +-1.68597399196934796817e-02, +-1.77771772107420643338e-02, +-1.86824583956837868282e-02, +-1.95750954364632238913e-02, +-2.04546085196391988492e-02, +-2.13205263092617232357e-02, +-2.21723861944465271134e-02, +-2.30097345315165013879e-02, +-2.38321268805886041231e-02, +-2.46391282364846579689e-02, +-2.54303132538467105417e-02, +-2.62052664663464558725e-02, +-2.69635824998752660075e-02, +-2.77048662796101873018e-02, +-2.84287332308504510359e-02, +-2.91348094735277007850e-02, +-2.98227320102924450818e-02, +-3.04921489080843266528e-02, +-3.11427194730996177718e-02, +-3.17741144190714572271e-02, +-3.23860160287801970846e-02, +-3.29781183087202514614e-02, +-3.35501271368501066683e-02, +-3.41017604033561905208e-02, +-3.46327481443660725735e-02, +-3.51428326685533573559e-02, +-3.56317686765738189658e-02, +-3.60993233732840035355e-02, +-3.65452765726929293399e-02, +-3.69694207956033291107e-02, +-3.73715613599018697810e-02, +-3.77515164634644601049e-02, +-3.81091172596444149878e-02, +-3.84442079253161372865e-02, +-3.87566457214516685292e-02, +-3.90463010462121923316e-02, +-3.93130574805393290250e-02, +-3.95568118262348833447e-02, +-3.97774741365262002324e-02, +-3.99749677391120911141e-02, +-4.01492292516929735746e-02, +-4.03002085899928502721e-02, +-4.04278689682822170437e-02, +-4.05321868924172351578e-02, +-4.06131521454162341955e-02, +-4.06707677655930785465e-02, +-4.07050500172784421316e-02, +-4.07160283541586343059e-02, +-4.07037453752667754969e-02, +-4.06682567736679767556e-02, +-4.06096312778803508747e-02, +-4.05279505860795044581e-02, +-4.04233092931398294012e-02, +-4.02958148105644620163e-02, +-4.01455872793672688403e-02, +-3.99727594759664850432e-02, +-3.97774767111586519119e-02, +-3.95598967222433872681e-02, +-3.93201895583720484328e-02, +-3.90585374591997241955e-02, +-3.87751347269212551239e-02, +-3.84701875917762628476e-02, +-3.81439140711113400251e-02, +-3.77965438220935409652e-02, +-3.74283179881668356948e-02, +-3.70394890393534528816e-02, +-3.66303206065006978220e-02, +-3.62010873095778978881e-02, +-3.57520745801320274926e-02, +-3.52835784780144504080e-02, +-3.47959055024906621645e-02, +-3.42893723978519651685e-02, +-3.37643059536492443073e-02, +-3.32210427996700446984e-02, +-3.26599291957861484481e-02, +-3.20813208167984795227e-02, +-3.14855825324110299990e-02, +-3.08730881824660075008e-02, +-3.02442203475766398235e-02, +-2.95993701152947666366e-02, +-2.89389368419537100496e-02, +-2.82633279103284111577e-02, +-2.75729584832571511521e-02, +-2.68682512533715799063e-02, +-2.61496361890828643570e-02, +-2.54175502769729139141e-02, +-2.46724372607451357398e-02, +-2.39147473768850267473e-02, +-2.31449370871867204924e-02, +-2.23634688083034216532e-02, +-2.15708106384762607344e-02, +-2.07674360816027074594e-02, +-1.99538237688046717067e-02, +-1.91304571776571320785e-02, +-1.82978243492389613944e-02, +-1.74564176031696584313e-02, +-1.66067332507972391376e-02, +-1.57492713066995013160e-02, +-1.48845351986653506166e-02, +-1.40130314763233891628e-02, +-1.31352695185807718387e-02, +-1.22517612400427650804e-02, +-1.13630207965765197414e-02, +-1.04695642901892153193e-02, +-9.57190947338527192700e-03, +-8.67057545317061195700e-03, +-7.76608239487228645126e-03, +-6.85895122593805847688e-03, +-5.94970333988319773771e-03, +-5.03886030055244581866e-03, +-4.12694354685914054082e-03, +-3.21447409816993977597e-03, +-2.30197226049791555877e-03, +-1.38995733366734314576e-03, +-4.78947319613120116137e-04, + 4.30541368021724365611e-04, + 1.33799419283328071238e-03, + 2.24289878298409997917e-03, + 3.14474521675841243995e-03, + 4.04302630618200674328e-03, + 4.93723787855436784672e-03, + 5.82687905573941924281e-03, + 6.71145253105821966433e-03, + 7.59046484363825723490e-03, + 8.46342665006433181318e-03, + 9.32985299318577973593e-03, + 1.01892635679366270335e-02, + 1.10411829840201432262e-02, + 1.18851410253191149685e-02, + 1.27206729058918742437e-02, + 1.35473195224164386086e-02, + 1.43646277029455919638e-02, + 1.51721504518438701781e-02, + 1.59694471907719792725e-02, + 1.67560839955920790056e-02, + 1.75316338290704282210e-02, + 1.82956767692504761180e-02, + 1.90478002333781711031e-02, + 1.97875991972636944283e-02, + 2.05146764099610016963e-02, + 2.12286426036550797403e-02, + 2.19291166986495568436e-02, + 2.26157260033451115722e-02, + 2.32881064091071711408e-02, + 2.39459025799248388655e-02, + 2.45887681367592640658e-02, + 2.52163658364931847489e-02, + 2.58283677453865524731e-02, + 2.64244554069528701790e-02, + 2.70043200041730317718e-02, + 2.75676625159635493856e-02, + 2.81141938678234649951e-02, + 2.86436350765866577783e-02, + 2.91557173892062447551e-02, + 2.96501824155063799238e-02, + 3.01267822548387659287e-02, + 3.05852796165800439043e-02, + 3.10254479344173710043e-02, + 3.14470714743682391856e-02, + 3.18499454364842490839e-02, + 3.22338760501942114822e-02, + 3.25986806632450124011e-02, + 3.29441878242012764488e-02, + 3.32702373584682215002e-02, + 3.35766804378105562789e-02, + 3.38633796433344125276e-02, + 3.41302090219154988238e-02, + 3.43770541360479547910e-02, + 3.46038121071011867125e-02, + 3.48103916519715006483e-02, + 3.49967131131205394512e-02, + 3.51627084819939664251e-02, + 3.53083214158219776957e-02, + 3.54335072478019763587e-02, + 3.55382329906705415890e-02, + 3.56224773336756214692e-02, + 3.56862306329609538236e-02, + 3.57294948953816096648e-02, + 3.57522837557707126588e-02, + 3.57546224476834179073e-02, + 3.57365477676438725307e-02, + 3.56981080329308309018e-02, + 3.56393630329330246553e-02, + 3.55603839741180857703e-02, + 3.54612534186531380698e-02, + 3.53420652167257473564e-02, + 3.52029244326149889921e-02, + 3.50439472645631341918e-02, + 3.48652609585071091014e-02, + 3.46670037157273194794e-02, + 3.44493245944778661571e-02, + 3.42123834056644454682e-02, + 3.39563506026385533709e-02, + 3.36814071651815385988e-02, + 3.33877444777541942944e-02, + 3.30755642020896523103e-02, + 3.27450781442136518162e-02, + 3.23965081159751852602e-02, + 3.20300857911755970653e-02, + 3.16460525563882003053e-02, + 3.12446593565609519183e-02, + 3.08261665354972284880e-02, + 3.03908436713170998500e-02, + 2.99389694069978791469e-02, + 2.94708312760984421363e-02, + 2.89867255237756110686e-02, + 2.84869569232016131566e-02, + 2.79718385874915022316e-02, + 2.74416917772590980562e-02, + 2.68968457039136660258e-02, + 2.63376373288174668585e-02, + 2.57644111584257248793e-02, + 2.51775190355282320331e-02, + 2.45773199267213977859e-02, + 2.39641797062345729419e-02, + 2.33384709362384548670e-02, + 2.27005726437677947394e-02, + 2.20508700943889204837e-02, + 2.13897545627447401018e-02, + 2.07176231001132207798e-02, + 2.00348782991160503930e-02, + 1.93419280557122104380e-02, + 1.86391853286192524242e-02, + 1.79270678963008890661e-02, + 1.72059981116597301987e-02, + 1.64764026545822124536e-02, + 1.57387122824750626260e-02, + 1.49933615789394694695e-02, + 1.42407887007263995321e-02, + 1.34814351231214504812e-02, + 1.27157453839016106739e-02, + 1.19441668260144781555e-02, + 1.11671493391258293271e-02, + 1.03851451001812210978e-02, + 9.59860831313457708858e-03, + 8.80799494798568949339e-03, + 8.01376247928074769700e-03, + 7.21636962422106571780e-03, + 6.41627608052837850733e-03, + 5.61394226421643282449e-03, + 4.80982904741692092465e-03, + 4.00439749640451800317e-03, + 3.19810860997276008924e-03, + 2.39142305830572152181e-03, + 1.58480092248966769435e-03, + 7.78701434814883992376e-04, +-2.64172799899629922237e-05, +-8.30098462447035776932e-04, +-1.63188697479669402902e-03, +-2.43132955610078941786e-03, +-3.22797507584321246785e-03, +-4.02137478588284608128e-03, +-4.81108257062173427093e-03, +-5.59665519525267239620e-03, +-6.37765255194445643272e-03, +-7.15363790383393653022e-03, +-7.92417812668915269581e-03, +-8.68884394811023953731e-03, +-9.44721018414002543240e-03, +-1.01988559731527404090e-02, +-1.09433650068938154165e-02, +-1.16803257585482624797e-02, +-1.24093317077095619677e-02, +-1.31299815621298259644e-02, +-1.38418794761330250093e-02, +-1.45446352655703541046e-02, +-1.52378646192042489088e-02, +-1.59211893064089386740e-02, +-1.65942373810739063344e-02, +-1.72566433816031643278e-02, +-1.79080485269053901742e-02, +-1.85481009082684548950e-02, +-1.91764556770177840850e-02, +-1.97927752278625780635e-02, +-2.03967293778293395912e-02, +-2.09879955406921600569e-02, +-2.15662588968082193086e-02, +-2.21312125582700525150e-02, +-2.26825577292899260851e-02, +-2.32200038617330316304e-02, +-2.37432688057198117149e-02, +-2.42520789552232059194e-02, +-2.47461693885826818085e-02, +-2.52252840038678892431e-02, +-2.56891756490234268728e-02, +-2.61376062467286660040e-02, +-2.65703469139121004061e-02, +-2.69871780758624488228e-02, +-2.73878895748791845177e-02, +-2.77722807734117477230e-02, +-2.81401606516388999579e-02, +-2.84913478994407130818e-02, +-2.88256710027211988934e-02, +-2.91429683240446539549e-02, +-2.94430881775452554794e-02, +-2.97258888980813616720e-02, +-2.99912389046026704731e-02, +-3.02390167577045836100e-02, +-3.04691112113477519108e-02, +-3.06814212587221760153e-02, +-3.08758561722402014027e-02, +-3.10523355376465907962e-02, +-3.12107892822333435334e-02, +-3.13511576971570726791e-02, +-3.14733914538524867099e-02, +-3.15774516145448311266e-02, +-3.16633096368639233020e-02, +-3.17309473725677151923e-02, +-3.17803570603852336696e-02, +-3.18115413129928040203e-02, +-3.18245130981409940496e-02, +-3.18192957139523252552e-02, +-3.17959227584129339172e-02, +-3.17544380930855907330e-02, +-3.16948958010739717528e-02, +-3.16173601392711264846e-02, +-3.15219054849285862385e-02, +-3.14086162765858309398e-02, +-3.12775869494028441187e-02, +-3.11289218649403939820e-02, +-3.09627352354390518452e-02, +-3.07791510426457977367e-02, +-3.05783029512460211019e-02, +-3.03603342169560183605e-02, +-3.01253975893385171625e-02, +-2.98736552094041353522e-02, +-2.96052785020640661651e-02, +-2.93204480635056198568e-02, +-2.90193535435597504968e-02, +-2.87021935231378082232e-02, +-2.83691753868116139370e-02, +-2.80205151906207892976e-02, +-2.76564375251866501060e-02, +-2.72771753742177547331e-02, +-2.68829699684970599427e-02, +-2.64740706354380586629e-02, +-2.60507346443026310823e-02, +-2.56132270471758974328e-02, +-2.51618205157945855344e-02, +-2.46967951743263178233e-02, +-2.42184384282035404523e-02, +-2.37270447891129755702e-02, +-2.32229156962464287906e-02, +-2.27063593339205324617e-02, +-2.21776904456732447402e-02, +-2.16372301449491780123e-02, +-2.10853057224852889762e-02, +-2.05222504505109502870e-02, +-1.99484033838788939186e-02, +-1.93641091582448833519e-02, +-1.87697177854121780016e-02, +-1.81655844459648781186e-02, +-1.75520692793087393357e-02, +-1.69295371712437116296e-02, +-1.62983575391910488761e-02, +-1.56589041152024530112e-02, +-1.50115547268741284653e-02, +-1.43566910762958008241e-02, +-1.36946985171622712812e-02, +-1.30259658301738225072e-02, +-1.23508849968591849500e-02, +-1.16698509719491937131e-02, +-1.09832614544311153726e-02, +-1.02915166574176798753e-02, +-9.59501907696169199780e-03, +-8.89417325994698755587e-03, +-8.18938557119236638926e-03, +-7.48106395989599822632e-03, +-6.76961772555855368499e-03, +-6.05545728351598779721e-03, +-5.33899393021318099950e-03, +-4.62063960835571319735e-03, +-3.90080667206999139041e-03, +-3.17990765220415401091e-03, +-2.45835502190418740687e-03, +-1.73656096259670639399e-03, +-1.01493713050778409414e-03, +-2.93894423852804689834e-04, + 4.26157249173980906629e-04, + 1.14480920148214617565e-03, + 1.86165419710703351590e-03, + 2.57628668004443710932e-03, + 3.28830300177243139287e-03, + 3.99730164732982774095e-03, + 4.70288345982820387564e-03, + 5.40465186327331818111e-03, + 6.10221308357093879249e-03, + 6.79517636759518171841e-03, + 7.48315420020127710504e-03, + 8.16576251905792339925e-03, + 8.84262092718743515640e-03, + 9.51335290309166317635e-03, + 1.01775860083515076043e-02, + 1.08349520925866381338e-02, + 1.14850874956621031020e-02, + 1.21276332470322649459e-02, + 1.27622352621157286734e-02, + 1.33885445355916270910e-02, + 1.40062173315140241908e-02, + 1.46149153701442997833e-02, + 1.52143060113965177677e-02, + 1.58040624348002624322e-02, + 1.63838638158842961334e-02, + 1.69533954988862062274e-02, + 1.75123491656954573259e-02, + 1.80604230009418498248e-02, + 1.85973218531409432985e-02, + 1.91227573918102446149e-02, + 1.96364482604763183893e-02, + 2.01381202254901497950e-02, + 2.06275063205740884220e-02, + 2.11043469870254470078e-02, + 2.15683902095024221390e-02, + 2.20193916473261919187e-02, + 2.24571147612263599669e-02, + 2.28813309354701996390e-02, + 2.32918195953102993845e-02, + 2.36883683196934501092e-02, + 2.40707729491726543647e-02, + 2.44388376889697125915e-02, + 2.47923752071377255513e-02, + 2.51312067277732788251e-02, + 2.54551621192373560276e-02, + 2.57640799773376678872e-02, + 2.60578077034374286369e-02, + 2.63362015774511563915e-02, + 2.65991268256962030969e-02, + 2.68464576835671930866e-02, + 2.70780774530085012464e-02, + 2.72938785547578652291e-02, + 2.74937625753404746298e-02, + 2.76776403087958637605e-02, + 2.78454317931197334324e-02, + 2.79970663414113134226e-02, + 2.81324825677129637669e-02, + 2.82516284075390901320e-02, + 2.83544611330882809219e-02, + 2.84409473631392593906e-02, + 2.85110630676332979516e-02, + 2.85647935669472025078e-02, + 2.86021335258679100522e-02, + 2.86230869422767590649e-02, + 2.86276671305612032126e-02, + 2.86158966997688939127e-02, + 2.85878075265257568238e-02, + 2.85434407227408461216e-02, + 2.84828465981240355753e-02, + 2.84060846175463004026e-02, + 2.83132233532735408388e-02, + 2.82043404321091033260e-02, + 2.80795224774836003900e-02, + 2.79388650465300265868e-02, + 2.77824725621904008999e-02, + 2.76104582403968873416e-02, + 2.74229440123787519823e-02, + 2.72200604421439854019e-02, + 2.70019466391913931513e-02, + 2.67687501665088492531e-02, + 2.65206269439171582469e-02, + 2.62577411468211084633e-02, + 2.59802651004316341454e-02, + 2.56883791695271083977e-02, + 2.53822716438199466604e-02, + 2.50621386190043350661e-02, + 2.47281838735542228158e-02, + 2.43806187413515146334e-02, + 2.40196619802195698856e-02, + 2.36455396364462083758e-02, + 2.32584849053751770154e-02, + 2.28587379881527788528e-02, + 2.24465459447181145403e-02, + 2.20221625431206817491e-02, + 2.15858481052626192953e-02, + 2.11378693491531578774e-02, + 2.06784992277722831644e-02, + 2.02080167646385595870e-02, + 1.97267068861813506253e-02, + 1.92348602510139590760e-02, + 1.87327730762112433516e-02, + 1.82207469606941833973e-02, + 1.76990887058239218521e-02, + 1.71681101333155360089e-02, + 1.66281279005709090035e-02, + 1.60794633135482208097e-02, + 1.55224421372705916056e-02, + 1.49573944040871566891e-02, + 1.43846542198004401919e-02, + 1.38045595677690705744e-02, + 1.32174521111029039805e-02, + 1.26236769930632777847e-02, + 1.20235826357873512582e-02, + 1.14175205374468860531e-02, + 1.08058450679664186378e-02, + 1.01889132634121089283e-02, + 9.56708461917343822023e-03, + 8.94072088205428300300e-03, + 8.31018584139599399141e-03, + 7.67584511934790540699e-03, + 7.03806596040880416698e-03, + 6.39721702035818493709e-03, + 5.75366815469682043455e-03, + 5.10779020672127558739e-03, + 4.45995479534525007814e-03, + 3.81053410279771258631e-03, + 3.15990066231072903868e-03, + 2.50842714592023827147e-03, + 1.85648615250139353144e-03, + 1.20444999615454471746e-03, + 5.52690495064260415084e-04, +-9.84212390521464980473e-05, +-7.48515010783776918966e-04, +-1.39722175004304473983e-03, +-2.04417372013348868851e-03, +-2.68900472475985721083e-03, +-3.33135031386035986023e-03, +-3.97084798814866836436e-03, +-4.60713740224857979527e-03, +-5.23986056631194768718e-03, +-5.86866204600630658739e-03, +-6.49318916075832062301e-03, +-7.11309218015082015546e-03, +-7.72802451835431433724e-03, +-8.33764292649709012895e-03, +-8.94160768285747094286e-03, +-9.53958278078098804997e-03, +-1.01312361142165130445e-02, +-1.07162396607681370542e-02, +-1.12942696621660988721e-02, +-1.18650068020553327297e-02, +-1.24281363810071557308e-02, +-1.29833484886548687631e-02, +-1.35303381728667914546e-02, +-1.40688056058569672252e-02, +-1.45984562471500062958e-02, +-1.51190010033104265535e-02, +-1.56301563843482677063e-02, +-1.61316446567209455243e-02, +-1.66231939928469449330e-02, +-1.71045386170529077619e-02, +-1.75754189478743681752e-02, +-1.80355817366393243739e-02, +-1.84847802022550938839e-02, +-1.89227741621333586663e-02, +-1.93493301591808192219e-02, +-1.97642215847910959758e-02, +-2.01672287977736237885e-02, +-2.05581392391563748390e-02, +-2.09367475428056254438e-02, +-2.13028556418044003051e-02, +-2.16562728705364630766e-02, +-2.19968160624214870147e-02, +-2.23243096432573610854e-02, +-2.26385857201165559272e-02, +-2.29394841657579208472e-02, +-2.32268526985093780313e-02, +-2.35005469575834645413e-02, +-2.37604305737897300577e-02, +-2.40063752356104789798e-02, +-2.42382607506086561466e-02, +-2.44559751021389444603e-02, +-2.46594145013394015764e-02, +-2.48484834343765149944e-02, +-2.50230947049280248728e-02, +-2.51831694718824584955e-02, +-2.53286372822437155783e-02, +-2.54594360992264553967e-02, +-2.55755123255348194855e-02, +-2.56768208218174157076e-02, +-2.57633249202947785250e-02, +-2.58349964335584103559e-02, +-2.58918156585436348704e-02, +-2.59337713756803804610e-02, +-2.59608608432293705426e-02, +-2.59730897868132928896e-02, +-2.59704723841564268094e-02, +-2.59530312450472130936e-02, +-2.59207973865424462501e-02, +-2.58738102034334269130e-02, +-2.58121174339979962686e-02, +-2.57357751210636476191e-02, +-2.56448475684109972184e-02, +-2.55394072925489191983e-02, +-2.54195349698946651551e-02, +-2.52853193793951269708e-02, +-2.51368573406296827444e-02, +-2.49742536474338513997e-02, +-2.47976209970892889911e-02, +-2.46070799151258470805e-02, +-2.44027586757840746212e-02, +-2.41847932181901530135e-02, +-2.39533270582963850326e-02, +-2.37085111966422665275e-02, +-2.34505040219958535430e-02, +-2.31794712109343950535e-02, +-2.28955856234271913630e-02, +-2.25990271944861188802e-02, +-2.22899828219497650461e-02, +-2.19686462504703923504e-02, +-2.16352179517750840831e-02, +-2.12899050012748461413e-02, +-2.09329209510937253036e-02, +-2.05644856995994759763e-02, +-2.01848253575104240320e-02, +-1.97941721106610450664e-02, +-1.93927640795097180892e-02, +-1.89808451754700721614e-02, +-1.85586649541545842257e-02, +-1.81264784656151936582e-02, +-1.76845461016740639060e-02, +-1.72331334404288091799e-02, +-1.67725110880316378992e-02, +-1.63029545178296972341e-02, +-1.58247439069643912324e-02, +-1.53381639705272194985e-02, +-1.48435037933645017777e-02, +-1.43410566596358455410e-02, +-1.38311198802215200299e-02, +-1.33139946180815798432e-02, +-1.27899857116674387641e-02, +-1.22594014964915645066e-02, +-1.17225536249535751410e-02, +-1.11797568845337768478e-02, +-1.06313290144546303273e-02, +-1.00775905209177212701e-02, +-9.51886449102469674177e-03, +-8.95547640548645211556e-03, +-8.38775395023088309043e-03, +-7.81602682701561073120e-03, +-7.24062656315801675411e-03, +-6.66188632048521009454e-03, +-6.08014070362140109788e-03, +-5.49572556771589591090e-03, +-4.90897782572374818955e-03, +-4.32023525535186938423e-03, +-3.72983630577348361859e-03, +-3.13811990422953454236e-03, +-2.54542526261991586267e-03, +-1.95209168419812327012e-03, +-1.35845837047655643853e-03, +-7.64864228454678000274e-04, +-1.71647678275262160000e-04, + 4.20853538580006714207e-04, + 1.01230255044841479378e-03, + 1.60236354589089790082e-03, + 2.19070196323387957060e-03, + 2.77698467914542839949e-03, + 3.36088019613725542609e-03, + 3.94205882888990985502e-03, + 4.52019288929302043289e-03, + 5.09495687010455642479e-03, + 5.66602762711795274880e-03, + 6.23308455974283786433e-03, + 6.79580978989625592024e-03, + 7.35388833910371412378e-03, + 7.90700830371526483531e-03, + 8.45486102813735630745e-03, + 8.99714127598559912369e-03, + 9.53354739906401085769e-03, + 1.00637815040785765647e-02, + 1.05875496169915012112e-02, + 1.11045618449284663742e-02, + 1.16145325355499640790e-02, + 1.21171804337962679687e-02, + 1.26122288359273460739e-02, + 1.30994057407662432141e-02, + 1.35784439980698272421e-02, + 1.40490814539434016872e-02, + 1.45110610932224059350e-02, + 1.49641311787415132173e-02, + 1.54080453874216524723e-02, + 1.58425629430952868981e-02, + 1.62674487460044807363e-02, + 1.66824734989000737773e-02, + 1.70874138296747413168e-02, + 1.74820524104663498066e-02, + 1.78661780731680860934e-02, + 1.82395859212837498087e-02, + 1.86020774380712544671e-02, + 1.89534605909168415994e-02, + 1.92935499318850137151e-02, + 1.96221666943946111694e-02, + 1.99391388859692132718e-02, + 2.02443013770143460939e-02, + 2.05374959855790205354e-02, + 2.08185715580545618875e-02, + 2.10873840457748047694e-02, + 2.13437965774761310989e-02, + 2.15876795275838501142e-02, + 2.18189105802902433284e-02, + 2.20373747893947494192e-02, + 2.22429646338771422331e-02, + 2.24355800691775179867e-02, + 2.26151285741611890456e-02, + 2.27815251937450065356e-02, + 2.29346925771693951890e-02, + 2.30745610118978684844e-02, + 2.32010684531324534730e-02, + 2.33141605489318240463e-02, + 2.34137906609261335633e-02, + 2.34999198806205046586e-02, + 2.35725170412852368107e-02, + 2.36315587254308061282e-02, + 2.36770292678692914623e-02, + 2.37089207543672679523e-02, + 2.37272330158955317703e-02, + 2.37319736184848778526e-02, + 2.37231578487003234856e-02, + 2.37008086947469512329e-02, + 2.36649568232238372012e-02, + 2.36156405515453339528e-02, + 2.35529058160507051567e-02, + 2.34768061358264293337e-02, + 2.33874025722661145477e-02, + 2.32847636843980104748e-02, + 2.31689654800100834631e-02, + 2.30400913626058086170e-02, + 2.28982320742268929958e-02, + 2.27434856341802542345e-02, + 2.25759572737094099670e-02, + 2.23957593666531708243e-02, + 2.22030113561352687723e-02, + 2.19978396773321642488e-02, + 2.17803776763693009155e-02, + 2.15507655253935614947e-02, + 2.13091501338791566855e-02, + 2.10556850562188986598e-02, + 2.07905303956600374937e-02, + 2.05138527046431831669e-02, + 2.02258248816056598884e-02, + 1.99266260643129536345e-02, + 1.96164415197817541825e-02, + 1.92954625308645287551e-02, + 1.89638862795599161259e-02, + 1.86219157271243600238e-02, + 1.82697594910530766721e-02, + 1.79076317190069930763e-02, + 1.75357519597588440430e-02, + 1.71543450312383258249e-02, + 1.67636408857523670768e-02, + 1.63638744724620595339e-02, + 1.59552855971977040894e-02, + 1.55381187796942588780e-02, + 1.51126231083333045085e-02, + 1.46790520924749527676e-02, + 1.42376635124681055061e-02, + 1.37887192674271304160e-02, + 1.33324852208636900064e-02, + 1.28692310442640404228e-02, + 1.23992300587048714933e-02, + 1.19227590745975605552e-02, + 1.14400982296555958628e-02, + 1.09515308251813669321e-02, + 1.04573431607620833533e-02, + 9.95782436747753331441e-03, + 9.45326623971061603957e-03, + 8.94396306566137833105e-03, + 8.43021145666009164010e-03, + 7.91231017538069313078e-03, + 7.39055996305047670919e-03, + 6.86526336575661762229e-03, + 6.33672455995178390137e-03, + 5.80524917725282890713e-03, + 5.27114412864063391212e-03, + 4.73471742815538901294e-03, + 4.19627801619143914885e-03, + 3.65613558249144616347e-03, + 3.11460038894114266822e-03, + 2.57198309226452578868e-03, + 2.02859456672282133238e-03, + 1.48474572691466213253e-03, + 9.40747350779479814438e-04, + 3.96909902906757746776e-04, +-1.46456641755227459385e-04, +-6.89042973683567970891e-04, +-1.23054062396519788870e-03, +-1.77064213877926087543e-03, +-2.30904125308122910865e-03, +-2.84543306338863035906e-03, +-3.37951419957442612471e-03, +-3.91098299557036087337e-03, +-4.43953965888237763598e-03, +-4.96488643882942240482e-03, +-5.48672779340401636783e-03, +-6.00477055466794654159e-03, +-6.51872409258721658559e-03, +-7.02830047721765636265e-03, +-7.53321463914807636086e-03, +-8.03318452811570618555e-03, +-8.52793126970340098492e-03, +-9.01717932003300026711e-03, +-9.50065661837041358639e-03, +-9.97809473755507415904e-03, +-1.04492290321770483347e-02, +-1.09137987844132033910e-02, +-1.13715473474486038208e-02, +-1.18222222864012831839e-02, +-1.22655755166751010560e-02, +-1.27013634396638160073e-02, +-1.31293470757343818528e-02, +-1.35492921944166400117e-02, +-1.39609694417272556244e-02, +-1.43641544645633414262e-02, +-1.47586280320936603927e-02, +-1.51441761540860777430e-02, +-1.55205901961063368055e-02, +-1.58876669915270080091e-02, +-1.62452089502858505743e-02, +-1.65930241643379994265e-02, +-1.69309265097449777870e-02, +-1.72587357453450260247e-02, +-1.75762776079578519894e-02, +-1.78833839040674798249e-02, +-1.81798925979421467647e-02, +-1.84656478961397856053e-02, +-1.87405003283600303521e-02, +-1.90043068245987142872e-02, +-1.92569307885670955305e-02, +-1.94982421673372645354e-02, +-1.97281175171806696933e-02, +-1.99464400655660206718e-02, +-2.01530997692852438530e-02, +-2.03479933686821802541e-02, +-2.05310244379545009386e-02, +-2.07021034315073952647e-02, +-2.08611477263374693603e-02, +-2.10080816604267042735e-02, +-2.11428365671300945439e-02, +-2.12653508055429402157e-02, +-2.13755697868347541157e-02, +-2.14734459965394662573e-02, +-2.15589390127965130350e-02, +-2.16320155205337663618e-02, +-2.16926493215929237779e-02, +-2.17408213407943202988e-02, +-2.17765196279432124427e-02, +-2.17997393557822147225e-02, +-2.18104828138950025684e-02, +-2.18087593985702259125e-02, +-2.17945855986363228041e-02, +-2.17679849772805522612e-02, +-2.17289881498666827275e-02, +-2.16776327577697588977e-02, +-2.16139634382471537699e-02, +-2.15380317903683393688e-02, +-2.14498963370269787876e-02, +-2.13496224830621826596e-02, +-2.12372824695176258547e-02, +-2.11129553240687953264e-02, +-2.09767268076514190600e-02, +-2.08286893573265061153e-02, +-2.06689420254178614356e-02, +-2.04975904149630808182e-02, +-2.03147466115173279400e-02, +-2.01205291113544029735e-02, +-1.99150627461096366155e-02, +-1.96984786039120784995e-02, +-1.94709139470550414430e-02, +-1.92325121262560613800e-02, +-1.89834224915587240767e-02, +-1.87238002999316095754e-02, +-1.84538066196213920711e-02, +-1.81736082313160018931e-02, +-1.78833775261818227198e-02, +-1.75832924008327562415e-02, +-1.72735361492968621244e-02, +-1.69542973520454935688e-02, +-1.66257697621504420271e-02, +-1.62881521886383481834e-02, +-1.59416483771111401613e-02, +-1.55864668877057875596e-02, +-1.52228209704614383946e-02, +-1.48509284381741404196e-02, +-1.44710115368087768872e-02, +-1.40832968135484268984e-02, +-1.36880149825567599964e-02, +-1.32854007885348044532e-02, +-1.28756928681500511930e-02, +-1.24591336094203239404e-02, +-1.20359690091351341501e-02, +-1.16064485283965002776e-02, +-1.11708249463664966578e-02, +-1.07293542123018670331e-02, +-1.02822952959679969620e-02, +-9.82991003651416048181e-03, +-9.37246298989989796990e-03, +-8.91022127496175937733e-03, +-8.44345441820766075269e-03, +-7.97243419742989060939e-03, +-7.49743448422606276194e-03, +-7.01873108552144003153e-03, +-6.53660158417858263430e-03, +-6.05132517879274946238e-03, +-5.56318252275954730490e-03, +-5.07245556271012591060e-03, +-4.57942737640496932289e-03, +-4.08438201018109132978e-03, +-3.58760431604305358652e-03, +-3.08937978849174819246e-03, +-2.58999440118657569057e-03, +-2.08973444352780410305e-03, +-1.58888635726068356765e-03, +-1.08773657318487516898e-03, +-5.86571348070346666216e-04, +-8.56766018661410432358e-05, + 4.14662244703500838458e-04, + 9.14160432062568030845e-04, + 1.41253402313765564872e-03, + 1.90950006404986844660e-03, + 2.40477674405564865318e-03, + 2.89808355464306636670e-03, + 3.38914144770032432427e-03, + 3.87767299266011901057e-03, + 4.36340253253783821180e-03, + 4.84605633877375780588e-03, + 5.32536276479152106272e-03, + 5.80105239818985360389e-03, + 6.27285821148045302093e-03, + 6.74051571128982465742e-03, + 7.20376308593877450609e-03, + 7.66234135132374139660e-03, + 8.11599449501146374963e-03, + 8.56446961847351709296e-03, + 9.00751707737854762081e-03, + 9.44489061986596677156e-03, + 9.87634752272530808126e-03, + 1.03016487254043390825e-02, + 1.07205589617752304610e-02, + 1.11328468895841945635e-02, + 1.15382852175153500368e-02, + 1.19366508297968510616e-02, + 1.23277249082861840856e-02, + 1.27112930519620286746e-02, + 1.30871453937629941139e-02, + 1.34550767147076835023e-02, + 1.38148865552336977403e-02, + 1.41663793236976622014e-02, + 1.45093644019762355729e-02, + 1.48436562481129210450e-02, + 1.51690744959529933561e-02, + 1.54854440517186581205e-02, + 1.57925951874666216368e-02, + 1.60903636313842884897e-02, + 1.63785906548734767896e-02, + 1.66571231563775630502e-02, + 1.69258137419078108499e-02, + 1.71845208022262455061e-02, + 1.74331085866468830925e-02, + 1.76714472734152173994e-02, + 1.78994130366322383441e-02, + 1.81168881096860183433e-02, + 1.83237608451629584161e-02, + 1.85199257712043326152e-02, + 1.87052836442837197573e-02, + 1.88797414983780387221e-02, + 1.90432126905080711943e-02, + 1.91956169426277314938e-02, + 1.93368803798427274510e-02, + 1.94669355649397177177e-02, + 1.95857215292121362993e-02, + 1.96931837995691326471e-02, + 1.97892744219159630314e-02, + 1.98739519807974267251e-02, + 1.99471816152978105585e-02, + 2.00089350311917421599e-02, + 2.00591905093446473685e-02, + 2.00979329103609591356e-02, + 2.01251536754834259302e-02, + 2.01408508237461286727e-02, + 2.01450289453875622248e-02, + 2.01376991915322746396e-02, + 2.01188792601508376068e-02, + 2.00885933783103917682e-02, + 2.00468722807307861422e-02, + 1.99937531846619727383e-02, + 1.99292797611018770998e-02, + 1.98535021023752838998e-02, + 1.97664766860958553141e-02, + 1.96682663355367028102e-02, + 1.95589401764357864733e-02, + 1.94385735902649521567e-02, + 1.93072481639931514685e-02, + 1.91650516363770367922e-02, + 1.90120778408122484415e-02, + 1.88484266447838007263e-02, + 1.86742038859517046900e-02, + 1.84895213049142380368e-02, + 1.82944964746886706841e-02, + 1.80892527269562349013e-02, + 1.78739190751135354485e-02, + 1.76486301341811334387e-02, + 1.74135260376162073759e-02, + 1.71687523510813504213e-02, + 1.69144599832216704915e-02, + 1.66508050935038308393e-02, + 1.63779489971747002630e-02, + 1.60960580673943053076e-02, + 1.58053036346042924398e-02, + 1.55058618831906466079e-02, + 1.51979137455046566657e-02, + 1.48816447933020276628e-02, + 1.45572451266690657684e-02, + 1.42249092604983910781e-02, + 1.38848360085833399946e-02, + 1.35372283653998979475e-02, + 1.31822933856448436252e-02, + 1.28202420616024131972e-02, + 1.24512891984102161413e-02, + 1.20756532873008502055e-02, + 1.16935563768882661712e-02, + 1.13052239425808411649e-02, + 1.09108847541921957086e-02, + 1.05107707418293280094e-02, + 1.01051168601380188944e-02, + 9.69416095097974661599e-03, + 9.27814360462589186873e-03, + 8.85730801954525207020e-03, + 8.43189986086877521498e-03, + 8.00216711761173211948e-03, + 7.56835995873902413200e-03, + 7.13073058815158738327e-03, + 6.68953309868379475400e-03, + 6.24502332519116971910e-03, + 5.79745869681476747037e-03, + 5.34709808850850412676e-03, + 4.89420167191210314650e-03, + 4.43903076565723645613e-03, + 3.98184768519108632512e-03, + 3.52291559220632970878e-03, + 3.06249834375802321845e-03, + 2.60086034116042237249e-03, + 2.13826637874443706636e-03, + 1.67498149256396322397e-03, + 1.21127080913929915072e-03, + 7.47399394318058719021e-04, + 2.83632102346346049587e-04, +-1.79766574769843468212e-04, +-6.42532657524515324506e-04, +-1.10440282870957989618e-03, +-1.56511458266390263150e-03, +-2.02440637389199361643e-03, +-2.48201776496643914185e-03, +-2.93768957363143169009e-03, +-3.39116401902536928475e-03, +-3.84218486693827703318e-03, +-4.29049757402515802296e-03, +-4.73584943089246784842e-03, +-5.17798970397907992042e-03, +-5.61666977614957031034e-03, +-6.05164328592657299599e-03, +-6.48266626527806404806e-03, +-6.90949727588800570455e-03, +-7.33189754383248466774e-03, +-7.74963109258556843290e-03, +-8.16246487428337087755e-03, +-8.57016889917199681248e-03, +-8.97251636316816550409e-03, +-9.36928377346218227428e-03, +-9.76025107209459868995e-03, +-1.01452017574365904035e-02, +-1.05239230035099728261e-02, +-1.08962057770798960432e-02, +-1.12618449524549517349e-02, +-1.16206394239357687498e-02, +-1.19723922158460008985e-02, +-1.23169105900894394756e-02, +-1.26540061511731961180e-02, +-1.29834949486409296365e-02, +-1.33051975768588605364e-02, +-1.36189392721043061457e-02, +-1.39245500069003491639e-02, +-1.42218645815492452517e-02, +-1.45107227128146703404e-02, +-1.47909691197041746891e-02, +-1.50624536063089509152e-02, +-1.53250311416544826582e-02, +-1.55785619365223330923e-02, +-1.58229115171997537781e-02, +-1.60579507961227489765e-02, +-1.62835561393713836031e-02, +-1.64996094309859363258e-02, +-1.67059981340693386453e-02, +-1.69026153486439532914e-02, +-1.70893598662360153562e-02, +-1.72661362211572987080e-02, +-1.74328547384603599335e-02, +-1.75894315785435489952e-02, +-1.77357887783837660234e-02, +-1.78718542893771675795e-02, +-1.79975620117707353629e-02, +-1.81128518256681338150e-02, +-1.82176696185966900676e-02, +-1.83119673096232941922e-02, +-1.83957028700091167195e-02, +-1.84688403403957639159e-02, +-1.85313498445167090800e-02, +-1.85832075994299093791e-02, +-1.86243959222697728906e-02, +-1.86549032335186701359e-02, +-1.86747240567995964611e-02, +-1.86838590151944261564e-02, +-1.86823148240932573882e-02, +-1.86701042805831954330e-02, +-1.86472462493857613075e-02, +-1.86137656453560576542e-02, +-1.85696934125556128992e-02, +-1.85150664999163827584e-02, +-1.84499278335122293693e-02, +-1.83743262854581951293e-02, +-1.82883166394587175219e-02, +-1.81919595530277734829e-02, +-1.80853215164069915100e-02, +-1.79684748082077037912e-02, +-1.78414974478062274277e-02, +-1.77044731445240056955e-02, +-1.75574912436227900669e-02, +-1.74006466691516183121e-02, +-1.72340398636801027388e-02, +-1.70577767249556339069e-02, +-1.68719685395252033677e-02, +-1.66767319133613971249e-02, +-1.64721886995365836281e-02, +-1.62584659229890703125e-02, +-1.60356957024269768108e-02, +-1.58040151694183554631e-02, +-1.55635663847157393325e-02, +-1.53144962518665349316e-02, +-1.50569564281600679762e-02, +-1.47911032329673657743e-02, +-1.45170975535258116318e-02, +-1.42351047482265624655e-02, +-1.39452945474637136913e-02, +-1.36478409521007416211e-02, +-1.33429221296188608992e-02, +-1.30307203080056444033e-02, +-1.27114216674486905923e-02, +-1.23852162298968091619e-02, +-1.20522977465561034055e-02, +-1.17128635833847836306e-02, +-1.13671146046554968900e-02, +-1.10152550546535922538e-02, +-1.06574924375795083986e-02, +-1.02940373957274844408e-02, +-9.92510358600978345733e-03, +-9.55090755489973984582e-03, +-9.17166861186629808755e-03, +-8.78760870137362294641e-03, +-8.39895227351954501427e-03, +-8.00592615338992057150e-03, +-7.60875940920200354023e-03, +-7.20768321931454427481e-03, +-6.80293073818321551022e-03, +-6.39473696133400267699e-03, +-5.98333858943855649570e-03, +-5.56897389156482680583e-03, +-5.15188256768454866386e-03, +-4.73230561051499881708e-03, +-4.31048516677632470584e-03, +-3.88666439794171014385e-03, +-3.46108734056119323949e-03, +-3.03399876624102851630e-03, +-2.60564404135369374893e-03, +-2.17626898656492900885e-03, +-1.74611973625276640544e-03, +-1.31544259790159325310e-03, +-8.84483911549698064228e-04, +-4.53489909372157390909e-04, +-2.27065754763732153979e-05, + 4.07620494008173754521e-04, + 8.37246230468182989909e-04, + 1.26592623189187344218e-03, + 1.69341690142426519808e-03, + 2.11947558531578586147e-03, + 2.54386071017997711027e-03, + 2.96633191949158747311e-03, + 3.38665020924181978113e-03, + 3.80457806267612890991e-03, + 4.21987958404042469429e-03, + 4.63232063125803249226e-03, + 5.04166894746706922836e-03, + 5.44769429133779015118e-03, + 5.85016856610528698801e-03, + 6.24886594723963670339e-03, + 6.64356300868360755141e-03, + 7.03403884758925946469e-03, + 7.42007520748272191013e-03, + 7.80145659978820089214e-03, + 8.17797042364491223732e-03, + 8.54940708395133565356e-03, + 8.91556010756844319332e-03, + 9.27622625762106536862e-03, + 9.63120564583299677841e-03, + 9.98030184283307808535e-03, + 1.03233219863735226768e-02, + 1.06600768874003729025e-02, + 1.09903811339163819116e-02, + 1.13140531925830963023e-02, + 1.16309155080034538898e-02, + 1.19407945996319476284e-02, + 1.22435211562607008245e-02, + 1.25389301280292575491e-02, + 1.28268608159079269826e-02, + 1.31071569586075614006e-02, + 1.33796668168697750756e-02, + 1.36442432550884507059e-02, + 1.39007438202245533349e-02, + 1.41490308179680942396e-02, + 1.43889713861080018736e-02, + 1.46204375650716145163e-02, + 1.48433063655967166505e-02, + 1.50574598334992579285e-02, + 1.52627851115045704011e-02, + 1.54591744981103021428e-02, + 1.56465255034476218021e-02, + 1.58247409021165554022e-02, + 1.59937287829656459015e-02, + 1.61534025957906987592e-02, + 1.63036811949317031467e-02, + 1.64444888797439722761e-02, + 1.65757554319247296659e-02, + 1.66974161496777871727e-02, + 1.68094118786993561299e-02, + 1.69116890399709611514e-02, + 1.70041996543472719028e-02, + 1.70869013639282085748e-02, + 1.71597574502064462165e-02, + 1.72227368489833373988e-02, + 1.72758141620482467971e-02, + 1.73189696656185082579e-02, + 1.73521893155377665563e-02, + 1.73754647492341991744e-02, + 1.73887932844398809817e-02, + 1.73921779146764994561e-02, + 1.73856273015124823678e-02, + 1.73691557636001317477e-02, + 1.73427832625017742940e-02, + 1.73065353853169359710e-02, + 1.72604433241233257146e-02, + 1.72045438522471921816e-02, + 1.71388792973795056618e-02, + 1.70634975115566134285e-02, + 1.69784518380263448056e-02, + 1.68838010750209793764e-02, + 1.67796094364609134353e-02, + 1.66659465096161037156e-02, + 1.65428872097501365734e-02, + 1.64105117317781858122e-02, + 1.62689054989683147545e-02, + 1.61181591087189469980e-02, + 1.59583682754456043784e-02, + 1.57896337706140629797e-02, + 1.56120613599556659623e-02, + 1.54257617379032624383e-02, + 1.52308504592903026092e-02, + 1.50274478683518758482e-02, + 1.48156790250726522890e-02, + 1.45956736289267492018e-02, + 1.43675659400543699606e-02, + 1.41314946979236334690e-02, + 1.38876030375264993694e-02, + 1.36360384031594637777e-02, + 1.33769524598382864855e-02, + 1.31105010024045141870e-02, + 1.28368438623721048408e-02, + 1.25561448125739872489e-02, + 1.22685714696633887261e-02, + 1.19742951945275791920e-02, + 1.16734909906738484192e-02, + 1.13663374006453127274e-02, + 1.10530164005323595922e-02, + 1.07337132926358554130e-02, + 1.04086165963493543218e-02, + 1.00779179373233617606e-02, + 9.74181193497532758874e-03, + 9.40049608841225445288e-03, + 9.05417066083279500899e-03, + 8.70303856247552944103e-03, + 8.34730523218016502718e-03, + 7.98717851763572177226e-03, + 7.62286855437785230982e-03, + 7.25458764361144089333e-03, + 6.88255012892701172750e-03, + 6.50697227198192371805e-03, + 6.12807212721856470888e-03, + 5.74606941569283727334e-03, + 5.36118539808457146567e-03, + 4.97364274696218688909e-03, + 4.58366541837830314410e-03, + 4.19147852286664863303e-03, + 3.79730819591561500129e-03, + 3.40138146799415100677e-03, + 3.00392613420201199520e-03, + 2.60517062362004749726e-03, + 2.20534386843704386522e-03, + 1.80467517292383881899e-03, + 1.40339408233299683948e-03, + 1.00173025179804741150e-03, + 5.99913315305479412538e-04, + 1.98172754814968598257e-04, +-2.03262230396802987941e-04, +-6.04162854095924620711e-04, +-1.00430087308224437644e-03, +-1.40344871673197396644e-03, +-1.80137961602673795508e-03, +-2.19786773199013999239e-03, +-2.59268828346089896114e-03, +-2.98561767413182141753e-03, +-3.37643361878200423329e-03, +-3.76491526863040370035e-03, +-4.15084333574143593548e-03, +-4.53400021641445216680e-03, +-4.91417011348194241599e-03, +-5.29113915745588105771e-03, +-5.66469552644815847742e-03, +-6.03462956480155590655e-03, +-6.40073390036281514998e-03, +-6.76280356033400701504e-03, +-7.12063608563857919354e-03, +-7.47403164373383350344e-03, +-7.82279313981379918752e-03, +-8.16672632633589495876e-03, +-8.50563991081211730194e-03, +-8.83934566180608928543e-03, +-9.16765851307686438498e-03, +-9.49039666581114917110e-03, +-9.80738168888878152074e-03, +-1.01184386171277399674e-02, +-1.04233960474500557403e-02, +-1.07220862329222184350e-02, +-1.10143451746142415071e-02, +-1.13000127112285256303e-02, +-1.15789326064506051250e-02, +-1.18509526339738002071e-02, +-1.21159246601509965058e-02, +-1.23737047242299964128e-02, +-1.26241531161297524527e-02, +-1.28671344517128152796e-02, +-1.31025177455174803715e-02, +-1.33301764809086713964e-02, +-1.35499886776097172580e-02, +-1.37618369565811367317e-02, +-1.39656086022109764133e-02, +-1.41611956217838150934e-02, +-1.43484948021984325128e-02, +-1.45274077639039357612e-02, +-1.46978410120258608934e-02, +-1.48597059846577242426e-02, +-1.50129190982918585967e-02, +-1.51574017903672395718e-02, +-1.52930805589124932387e-02, +-1.54198869992662364325e-02, +-1.55377578378534803027e-02, +-1.56466349630057406650e-02, +-1.57464654528072754702e-02, +-1.58372015999561979727e-02, +-1.59188009336289001960e-02, +-1.59912262383383775577e-02, +-1.60544455697791341175e-02, +-1.61084322676517156803e-02, +-1.61531649654640882541e-02, +-1.61886275973061356803e-02, +-1.62148094015971411253e-02, +-1.62317049218069497929e-02, +-1.62393140041536092333e-02, +-1.62376417922817130324e-02, +-1.62266987189277553383e-02, +-1.62065004945800873737e-02, +-1.61770680931431522220e-02, +-1.61384277346172493040e-02, +-1.60906108648061207944e-02, +-1.60336541320681771894e-02, +-1.59675993611263326855e-02, +-1.58924935239547066024e-02, +-1.58083887077626328299e-02, +-1.57153420800955900827e-02, +-1.56134158510770112288e-02, +-1.55026772328152578212e-02, +-1.53831983960010937329e-02, +-1.52550564237238350102e-02, +-1.51183332625351458250e-02, +-1.49731156707911920722e-02, +-1.48194951643046812090e-02, +-1.46575679593417048524e-02, +-1.44874349129977750272e-02, +-1.43092014609884597698e-02, +-1.41229775528962445130e-02, +-1.39288775849084438263e-02, +-1.37270203300904457960e-02, +-1.35175288662355702618e-02, +-1.33005305013339011205e-02, +-1.30761566967065763489e-02, +-1.28445429878512040744e-02, +-1.26058289030446593615e-02, +-1.23601578797534680798e-02, +-1.21076771789009329794e-02, +-1.18485377970418380433e-02, +-1.15828943764964987367e-02, +-1.13109051134989493925e-02, +-1.10327316644120605738e-02, +-1.07485390500640064226e-02, +-1.04584955582669985458e-02, +-1.01627726445692283253e-02, +-9.86154483130371323218e-03, +-9.55498960498988268719e-03, +-9.24328731215033269630e-03, +-8.92662105360215486771e-03, +-8.60517657728362625469e-03, +-8.27914216968341290515e-03, +-7.94870854592883563372e-03, +-7.61406873860231547119e-03, +-7.27541798534921645147e-03, +-6.93295361534090708033e-03, +-6.58687493466020984600e-03, +-6.23738311067596751247e-03, +-5.88468105547270119854e-03, +-5.52897330840119299866e-03, +-5.17046591782320454772e-03, +-4.80936632211110496465e-03, +-4.44588322997643489720e-03, +-4.08022650019468531568e-03, +-3.71260702079436550813e-03, +-3.34323658778045351356e-03, +-2.97232778346277022249e-03, +-2.60009385445763652536e-03, +-2.22674858943125442146e-03, +-1.85250619666033739495e-03, +-1.47758118147215886107e-03, +-1.10218822363969577716e-03, +-7.26542054800227666764e-04, +-3.50857335965947274205e-04, + 2.46514648028058004550e-05, + 3.99770194491305848588e-04, + 7.74285136923100344129e-04, + 1.14798313418393348531e-03, + 1.52065170760259482478e-03, + 1.89207917822773732594e-03, + 2.26205478672706098917e-03, + 2.63036881264248683862e-03, + 2.99681269293534556161e-03, + 3.36117913975389048103e-03, + 3.72326225735529307836e-03, + 4.08285765811985511958e-03, + 4.43976257758913958607e-03, + 4.79377598846415613199e-03, + 5.14469871350105301122e-03, + 5.49233353723946847447e-03, + 5.83648531650244987989e-03, + 6.17696108960405759064e-03, + 6.51357018420694721533e-03, + 6.84612432376711325249e-03, + 7.17443773250708155542e-03, + 7.49832723886042704087e-03, + 7.81761237732933426947e-03, + 8.13211548869811375051e-03, + 8.44166181854820452113e-03, + 8.74607961402130464068e-03, + 9.04520021877286591050e-03, + 9.33885816606978835797e-03, + 9.62689126997642689865e-03, + 9.90914071458013148708e-03, + 1.01854511412086366773e-02, + 1.04556707335903883299e-02, + 1.07196513009111780990e-02, + 1.09772483587224512630e-02, + 1.12283212076583951283e-02, + 1.14727330099153260884e-02, + 1.17103508634570831898e-02, + 1.19410458739028241953e-02, + 1.21646932240592649255e-02, + 1.23811722410611373818e-02, + 1.25903664610832344978e-02, + 1.27921636915890018366e-02, + 1.29864560710836914048e-02, + 1.31731401263407224556e-02, + 1.33521168270687006635e-02, + 1.35232916379940497353e-02, + 1.36865745683296211738e-02, + 1.38418802186039205382e-02, + 1.39891278248280535867e-02, + 1.41282412999769145523e-02, + 1.42591492727635726218e-02, + 1.43817851236876445564e-02, + 1.44960870183408006145e-02, + 1.46019979379505230460e-02, + 1.46994657071504129797e-02, + 1.47884430189622918805e-02, + 1.48688874569784020702e-02, + 1.49407615147348158541e-02, + 1.50040326122672287162e-02, + 1.50586731098424179975e-02, + 1.51046603188603172779e-02, + 1.51419765099236949824e-02, + 1.51706089180728420640e-02, + 1.51905497451859678587e-02, + 1.52017961595458175883e-02, + 1.52043502925764267841e-02, + 1.51982192327537388166e-02, + 1.51834150166969984036e-02, + 1.51599546174485608208e-02, + 1.51278599299513004384e-02, + 1.50871577537351683751e-02, + 1.50378797728247023263e-02, + 1.49800625328825147420e-02, + 1.49137474156039364498e-02, + 1.48389806103799235665e-02, + 1.47558130832480607908e-02, + 1.46643005431505314001e-02, + 1.45645034055218620950e-02, + 1.44564867532300453390e-02, + 1.43403202948947962325e-02, + 1.42160783206099778503e-02, + 1.40838396550982923594e-02, + 1.39436876083266405452e-02, + 1.37957099236124917929e-02, + 1.36399987232554212313e-02, + 1.34766504517241942490e-02, + 1.33057658164359091102e-02, + 1.31274497261638489060e-02, + 1.29418112271095040594e-02, + 1.27489634366789363756e-02, + 1.25490234750032566419e-02, + 1.23421123942442402532e-02, + 1.21283551057263516704e-02, + 1.19078803049420742233e-02, + 1.16808203944710996269e-02, + 1.14473114048624195760e-02, + 1.12074929135256729645e-02, + 1.09615079616787580025e-02, + 1.07095029694022052941e-02, + 1.04516276488501973219e-02, + 1.01880349156695994978e-02, + 9.91888079867737047779e-03, + 9.64432434785405211242e-03, + 9.36452754070147760923e-03, + 9.07965518702451984678e-03, + 8.78987483218966227094e-03, + 8.49535665891908500780e-03, + 8.19627338767603061398e-03, + 7.89280017569949157719e-03, + 7.58511451474948479590e-03, + 7.27339612761909639488e-03, + 6.95782686347547630473e-03, + 6.63859059209071476759e-03, + 6.31587309702252765881e-03, + 5.98986196780740103029e-03, + 5.66074649122982193061e-03, + 5.32871754172747295192e-03, + 4.99396747099837244599e-03, + 4.65668999687305143476e-03, + 4.31708009151461624686e-03, + 3.97533386901183748152e-03, + 3.63164847243082006614e-03, + 3.28622196038877781299e-03, + 2.93925319321392116909e-03, + 2.59094171876164420382e-03, + 2.24148765794563754883e-03, + 1.89109159005432995830e-03, + 1.53995443791703993247e-03, + 1.18827735298423120720e-03, + 8.36261600388259543348e-04, + 4.84108444050918994457e-04, + 1.32019031902150203511e-04, +-2.19805718726241933539e-04, +-5.71165235461442008166e-04, +-9.21859404947263896997e-04, +-1.27168868652862017930e-03, +-1.62045422549978823494e-03, +-1.96795796585350459343e-03, +-2.31400276246625583032e-03, +-2.65839249265560281787e-03, +-3.00093216704766258679e-03, +-3.34142803969362210681e-03, +-3.67968771736809294182e-03, +-4.01552026799475991758e-03, +-4.34873632813331280345e-03, +-4.67914820946864051104e-03, +-5.00657000424378773040e-03, +-5.33081768957552153132e-03, +-5.65170923059745127642e-03, +-5.96906468236742954181e-03, +-6.28270629048909966946e-03, +-6.59245859038667947338e-03, +-6.89814850517884731868e-03, +-7.19960544209851966563e-03, +-7.49666138740393440260e-03, +-7.78915099972798865430e-03, +-8.07691170181503576009e-03, +-8.35978377059490469769e-03, +-8.63761042554191810217e-03, +-8.91023791527316942618e-03, +-9.17751560233688937207e-03, +-9.43929604614376221994e-03, +-9.69543508399723329150e-03, +-9.94579191017774290329e-03, +-1.01902291530364327854e-02, +-1.04286129500589536817e-02, +-1.06608130208563391117e-02, +-1.08867027380436017653e-02, +-1.11061591959687958747e-02, +-1.13190632772547025708e-02, +-1.15252997171166309681e-02, +-1.17247571654230976768e-02, +-1.19173282464660659080e-02, +-1.21029096164066742036e-02, +-1.22814020183694711658e-02, +-1.24527103351532476838e-02, +-1.26167436395315489539e-02, +-1.27734152421167899277e-02, +-1.29226427367628814158e-02, +-1.30643480434822645969e-02, +-1.31984574488560428562e-02, +-1.33249016439166492742e-02, +-1.34436157594821689004e-02, +-1.35545393989273295354e-02, +-1.36576166683727209111e-02, +-1.37527962042781285584e-02, +-1.38400311984271696952e-02, +-1.39192794202912337870e-02, +-1.39905032367616116717e-02, +-1.40536696292427546601e-02, +-1.41087502080980680547e-02, +-1.41557212244426133818e-02, +-1.41945635792792845820e-02, +-1.42252628299752575947e-02, +-1.42478091940773932134e-02, +-1.42621975504671379131e-02, +-1.42684274378570910558e-02, +-1.42665030506319845394e-02, +-1.42564332320393345743e-02, +-1.42382314647362499815e-02, +-1.42119158586999447952e-02, +-1.41775091365116089059e-02, +-1.41350386160245498901e-02, +-1.40845361904284333693e-02, +-1.40260383057241797000e-02, +-1.39595859356245310251e-02, +-1.38852245538964112065e-02, +-1.38030041041644433580e-02, +-1.37129789671941813151e-02, +-1.36152079256764129561e-02, +-1.35097541265353955631e-02, +-1.33966850407841280013e-02, +-1.32760724209521549510e-02, +-1.31479922561130030401e-02, +-1.30125247245378994343e-02, +-1.28697541440061513640e-02, +-1.27197689198022458740e-02, +-1.25626614904315592192e-02, +-1.23985282710872991158e-02, +-1.22274695949040924925e-02, +-1.20495896520329080076e-02, +-1.18649964265733695590e-02, +-1.16738016314043534238e-02, +-1.14761206409479885049e-02, +-1.12720724219102334807e-02, +-1.10617794620386598187e-02, +-1.08453676969394192248e-02, +-1.06229664349969266796e-02, +-1.03947082804420436186e-02, +-1.01607290546128509884e-02, +-9.92116771545450623626e-03, +-9.67616627530844784777e-03, +-9.42586971703506318332e-03, +-9.17042590852275470159e-03, +-8.90998551563223703531e-03, +-8.64470191362698078819e-03, +-8.37473109714258721892e-03, +-8.10023158874558640852e-03, +-7.82136434613948418326e-03, +-7.53829266806671071527e-03, +-7.25118209896521460911e-03, +-6.96020033243441478554e-03, +-6.66551711356555987714e-03, +-6.36730414019388325786e-03, +-6.06573496313063138113e-03, +-5.76098488543169522103e-03, +-5.45323086076018610086e-03, +-5.14265139090599315841e-03, +-4.82942642251557672367e-03, +-4.51373724309595599630e-03, +-4.19576637635184213071e-03, +-3.87569747691505085002e-03, +-3.55371522452749104282e-03, +-3.23000521773942998738e-03, +-2.90475386718291829144e-03, +-2.57814828848035217795e-03, +-2.25037619485449289641e-03, +-1.92162578949469156631e-03, +-1.59208565774584761589e-03, +-1.26194465918040934528e-03, +-9.31391819614034682621e-04, +-6.00616223127062396486e-04, +-2.69806904154944583816e-04, + 6.08472602942396962656e-05, + 3.91157658230999324359e-04, + 7.20936050023826264892e-04, + 1.04999467542699867657e-03, + 1.37814636023528779528e-03, + 1.70520462250435696737e-03, + 2.03098377827778953097e-03, + 2.35529904676215007600e-03, + 2.67796665488591583565e-03, + 2.99880394118968215261e-03, + 3.31762945898433653930e-03, + 3.63426307872031237670e-03, + 3.94852608951128981885e-03, + 4.26024129975459756037e-03, + 4.56923313679098372364e-03, + 4.87532774554888699570e-03, + 5.17835308611915706711e-03, + 5.47813903020093976443e-03, + 5.77451745637115685522e-03, + 6.06732234411917498856e-03, + 6.35638986659726578504e-03, + 6.64155848203327753981e-03, + 6.92266902375569294359e-03, + 7.19956478878218397721e-03, + 7.47209162491841317327e-03, + 7.74009801632427347357e-03, + 8.00343516749617983619e-03, + 8.26195708562018661658e-03, + 8.51552066125116358108e-03, + 8.76398574727313937893e-03, + 9.00721523609652845177e-03, + 9.24507513505131058029e-03, + 9.47743463993477690266e-03, + 9.70416620667113177801e-03, + 9.92514562104791428498e-03, + 1.01402520664879789575e-02, + 1.03493681898213143316e-02, + 1.05523801650215433984e-02, + 1.07491777548722518970e-02, + 1.09396543705291681564e-02, + 1.11237071289475124292e-02, + 1.13012369081435404966e-02, + 1.14721484002587425371e-02, + 1.16363501624019635705e-02, + 1.17937546652395908869e-02, + 1.19442783393092378380e-02, + 1.20878416190330750107e-02, + 1.22243689844071853207e-02, + 1.23537890003452277554e-02, + 1.24760343536569357631e-02, + 1.25910418876418357670e-02, + 1.26987526342805939761e-02, + 1.27991118440086270452e-02, + 1.28920690130565843839e-02, + 1.29775779083439509604e-02, + 1.30555965899154108323e-02, + 1.31260874309076600724e-02, + 1.31890171350384308863e-02, + 1.32443567516100473014e-02, + 1.32920816880211477284e-02, + 1.33321717197816842077e-02, + 1.33646109980275606260e-02, + 1.33893880545334492682e-02, + 1.34064958042229027263e-02, + 1.34159315451764481197e-02, + 1.34176969561404253045e-02, + 1.34117980915397661673e-02, + 1.33982453740004014281e-02, + 1.33770535843872502568e-02, + 1.33482418493662668285e-02, + 1.33118336264995938689e-02, + 1.32678566868845784765e-02, + 1.32163430953490413505e-02, + 1.31573291882161602651e-02, + 1.30908555486537094698e-02, + 1.30169669796242129522e-02, + 1.29357124744537473754e-02, + 1.28471451850375104065e-02, + 1.27513223877034967413e-02, + 1.26483054467555582068e-02, + 1.25381597757181027092e-02, + 1.24209547963076202132e-02, + 1.22967638951557260707e-02, + 1.21656643783110817586e-02, + 1.20277374235470257274e-02, + 1.18830680305065279623e-02, + 1.17317449687113807555e-02, + 1.15738607234699020926e-02, + 1.14095114397158373110e-02, + 1.12387968638101957974e-02, + 1.10618202833434337712e-02, + 1.08786884649728424201e-02, + 1.06895115903328993823e-02, + 1.04944031900558870651e-02, + 1.02934800759447477037e-02, + 1.00868622713343389363e-02, + 9.87467293968604525878e-03, + 9.65703831145729371666e-03, + 9.43408760928757944564e-03, + 9.20595297154692439323e-03, + 8.97276937429128222667e-03, + 8.73467455167086133383e-03, + 8.49180891483720598489e-03, + 8.24431546939977458188e-03, + 7.99233973147535532722e-03, + 7.73602964238361088395e-03, + 7.47553548203802858269e-03, + 7.21100978108041128223e-03, + 6.94260723181349802963e-03, + 6.67048459797950268196e-03, + 6.39480062344236106775e-03, + 6.11571593982157112740e-03, + 5.83339297313448506416e-03, + 5.54799584949982379362e-03, + 5.25969029995765075675e-03, + 4.96864356445977841531e-03, + 4.67502429508827137272e-03, + 4.37900245855606801149e-03, + 4.08074923804454484794e-03, + 3.78043693443984004168e-03, + 3.47823886701886190315e-03, + 3.17432927364564567915e-03, + 2.86888321053426365720e-03, + 2.56207645163618802017e-03, + 2.25408538770850491381e-03, + 1.94508692512463700341e-03, + 1.63525838447931698427e-03, + 1.32477739905105789536e-03, + 1.01382181317911045614e-03, + 7.02569580610471595104e-04, + 3.91198662877513612512e-04, + 7.98869277630744821202e-05, +-2.31187952088860002205e-04, +-5.41848600360482837712e-04, +-8.51918037984115972261e-04, +-1.16121978375175968247e-03, +-1.46957795454782155081e-03, +-1.77681736514933067382e-03, +-2.08276362753950002732e-03, +-2.38724324967590261284e-03, +-2.69008373365854430367e-03, +-2.99111367324205812759e-03, +-3.29016285063819195061e-03, +-3.58706233255040498470e-03, +-3.88164456539251325612e-03, +-4.17374346963266494581e-03, +-4.46319453321069280205e-03, +-4.74983490397884282330e-03, +-5.03350348111142233826e-03, +-5.31404100543327127110e-03, +-5.59129014861656486318e-03, +-5.86509560119571633080e-03, +-6.13530415935167362795e-03, +-6.40176481041693050400e-03, +-6.66432881705371002456e-03, +-6.92284980005934951625e-03, +-7.17718381975063907108e-03, +-7.42718945588436395278e-03, +-7.67272788607022311613e-03, +-7.91366296262873900047e-03, +-8.14986128785674147912e-03, +-8.38119228765579413198e-03, +-8.60752828348398772718e-03, +-8.82874456259165676930e-03, +-9.04471944650279101319e-03, +-9.25533435770336740389e-03, +-9.46047388450147082317e-03, +-9.66002584402477111614e-03, +-9.85388134331765391805e-03, +-1.00419348385086572295e-02, +-1.02240841920141073418e-02, +-1.04002307277476988001e-02, +-1.05702792843059330957e-02, +-1.07341382661022052142e-02, +-1.08917196924194058932e-02, +-1.10429392443588056394e-02, +-1.11877163096573035983e-02, +-1.13259740253500613971e-02, +-1.14576393182570599599e-02, +-1.15826429432718831097e-02, +-1.17009195194323206701e-02, +-1.18124075637551975010e-02, +-1.19170495228175868374e-02, +-1.20147918020679297935e-02, +-1.21055847928538372338e-02, +-1.21893828971518514148e-02, +-1.22661445499873279080e-02, +-1.23358322395343555922e-02, +-1.23984125248859967938e-02, +-1.24538560514863300838e-02, +-1.25021375642184340987e-02, +-1.25432359181423137146e-02, +-1.25771340868788758516e-02, +-1.26038191686375488504e-02, +-1.26232823898858471240e-02, +-1.26355191066611412948e-02, +-1.26405288035257891421e-02, +-1.26383150901686648615e-02, +-1.26288856956566081235e-02, +-1.26122524603418419142e-02, +-1.25884313254311982350e-02, +-1.25574423202261184485e-02, +-1.25193095470420810711e-02, +-1.24740611638184551585e-02, +-1.24217293644305545874e-02, +-1.23623503567175385687e-02, +-1.22959643382403553680e-02, +-1.22226154697852723574e-02, +-1.21423518466312625047e-02, +-1.20552254675984453491e-02, +-1.19612922018975387228e-02, +-1.18606117538015195384e-02, +-1.17532476251614014656e-02, +-1.16392670757887554955e-02, +-1.15187410817310965927e-02, +-1.13917442914640253127e-02, +-1.12583549800273283181e-02, +-1.11186550011346148292e-02, +-1.09727297372832800770e-02, +-1.08206680478965637515e-02, +-1.06625622155284947856e-02, +-1.04985078901642363974e-02, +-1.03286040316486818491e-02, +-1.01529528502798636891e-02, +-9.97165974559921335085e-03, +-9.78483324341799902413e-03, +-9.59258493111724702684e-03, +-9.39502939125761923900e-03, +-9.19228413354054689488e-03, +-8.98446952515993303712e-03, +-8.77170871958610903762e-03, +-8.55412758382280251357e-03, +-8.33185462418275894769e-03, +-8.10502091062164677082e-03, +-7.87375999967769406307e-03, +-7.63820785606213713270e-03, +-7.39850277294432437381e-03, +-7.15478529097991495372e-03, +-6.90719811612892573005e-03, +-6.65588603631140588585e-03, +-6.40099583694948154333e-03, +-6.14267621544471731365e-03, +-5.88107769464080425842e-03, +-5.61635253532167481177e-03, +-5.34865464779504806714e-03, +-5.07813950261468052133e-03, +-4.80496404049110190093e-03, +-4.52928658144188898277e-03, +-4.25126673323850644282e-03, +-3.97106529919719845184e-03, +-3.68884418537053504483e-03, +-3.40476630719170527545e-03, +-3.11899549562579155026e-03, +-2.83169640288094461716e-03, +-2.54303440773591491603e-03, +-2.25317552053609778881e-03, +-1.96228628791152723623e-03, +-1.67053369727637865058e-03, +-1.37808508115876398453e-03, +-1.08510802141915333602e-03, +-7.91770253410941553598e-04, +-4.98239570138193856204e-04, +-2.04683726464174046067e-04, + 8.87296565722855913767e-05, + 3.81833187280424608996e-04, + 6.74459798627879405716e-04, + 9.66442843278491714280e-04, + 1.25761618830957477670e-03, + 1.54781430955123577679e-03, + 1.83687238549551422676e-03, + 2.12462639072184518788e-03, + 2.41091318878710377666e-03, + 2.69557062452432027663e-03, + 2.97843761570351769560e-03, + 3.25935424399821128960e-03, + 3.53816184520730405566e-03, + 3.81470309868363116265e-03, + 4.08882211591671436424e-03, + 4.36036452822079721725e-03, + 4.62917757347863778605e-03, + 4.89511018189369654513e-03, + 5.15801306069900780682e-03, + 5.41773877778122490978e-03, + 5.67414184416796703314e-03, + 5.92707879533384274229e-03, + 6.17640827128176569949e-03, + 6.42199109535173794788e-03, + 6.66369035171747361307e-03, + 6.90137146152226561152e-03, + 7.13490225761727499265e-03, + 7.36415305785760327534e-03, + 7.58899673691662904340e-03, + 7.80930879657879342681e-03, + 8.02496743447280412587e-03, + 8.23585361120545214608e-03, + 8.44185111586123922145e-03, + 8.64284662983217863430e-03, + 8.83872978893951791179e-03, + 9.02939324381753054272e-03, + 9.21473271852386519032e-03, + 9.39464706734555871082e-03, + 9.56903832976962673285e-03, + 9.73781178358892364477e-03, + 9.90087599611340699046e-03, + 1.00581428734606900116e-02, + 1.02095277078994902537e-02, + 1.03549492232184597862e-02, + 1.04943296180992785144e-02, + 1.06275946074688987242e-02, + 1.07546734618099455033e-02, + 1.08754990444085344187e-02, + 1.09900078465200706085e-02, + 1.10981400204346221383e-02, + 1.11998394104246661029e-02, + 1.12950535815609064139e-02, + 1.13837338463788559362e-02, + 1.14658352893853201365e-02, + 1.15413167893916573242e-02, + 1.16101410396627392763e-02, + 1.16722745658728050550e-02, + 1.17276877418591822522e-02, + 1.17763548031668534993e-02, + 1.18182538583788306064e-02, + 1.18533668982268927672e-02, + 1.18816798024796634742e-02, + 1.19031823446065308097e-02, + 1.19178681942160510920e-02, + 1.19257349172696772155e-02, + 1.19267839740727354947e-02, + 1.19210207150453346286e-02, + 1.19084543742781455433e-02, + 1.18890980608779301547e-02, + 1.18629687481103703039e-02, + 1.18300872603478539336e-02, + 1.17904782578316710134e-02, + 1.17441702192595375659e-02, + 1.16911954222092898115e-02, + 1.16315899214134987893e-02, + 1.15653935248972560695e-02, + 1.14926497679962574816e-02, + 1.14134058852708338005e-02, + 1.13277127803342991114e-02, + 1.12356249936141419643e-02, + 1.11372006680669592693e-02, + 1.10325015128680588988e-02, + 1.09215927650972884078e-02, + 1.08045431494469181682e-02, + 1.06814248359739724648e-02, + 1.05523133959240563579e-02, + 1.04172877556533635679e-02, + 1.02764301486764821764e-02, + 1.01298260658689662922e-02, + 9.97756420385554482211e-03, + 9.81973641161405612354e-03, + 9.65643763532623641832e-03, + 9.48776586151135747915e-03, + 9.31382205847339390836e-03, + 9.13471011609818910049e-03, + 8.95053678403625804783e-03, + 8.76141160830776546953e-03, + 8.56744686636650917833e-03, + 8.36875750066302069585e-03, + 8.16546105074440926874e-03, + 7.95767758393019740415e-03, + 7.74552962460837469971e-03, + 7.52914208218922759858e-03, + 7.30864217776142511412e-03, + 7.08415936949292109753e-03, + 6.85582527682011919762e-03, + 6.62377360346902248345e-03, + 6.38814005935512633366e-03, + 6.14906228140583120678e-03, + 5.90667975335047463342e-03, + 5.66113372452884365538e-03, + 5.41256712776044118796e-03, + 5.16112449632528166171e-03, + 4.90695188010295546555e-03, + 4.65019676091923093997e-03, + 4.39100796714859270553e-03, + 4.12953558762247860403e-03, + 3.86593088489268566291e-03, + 3.60034620790024339002e-03, + 3.33293490409898975416e-03, + 3.06385123108688468482e-03, + 2.79325026779358087312e-03, + 2.52128782527450854764e-03, + 2.24812035716717229308e-03, + 1.97390486985574153955e-03, + 1.69879883239866091155e-03, + 1.42296008626978756108e-03, + 1.14654675496503560654e-03, + 8.69717153525156449340e-04, + 5.92629698028697892917e-04, + 3.15442815104587483740e-04, + 3.83148515150130003753e-05, +-2.38596016135179852516e-04, +-5.15131871516745108372e-04, +-7.91135148467245652611e-04, +-1.06644872060530828545e-03, +-1.34091599061669417524e-03, +-1.61438097916256320837e-03, +-1.88668841335719902723e-03, +-2.15768381476730232091e-03, +-2.42721358688397208930e-03, +-2.69512510201327460183e-03, +-2.96126678754182314640e-03, +-3.22548821152533965809e-03, +-3.48764016755303369807e-03, +-3.74757475883982088538e-03, +-4.00514548149979391495e-03, +-4.26020730695223729528e-03, +-4.51261676341580680871e-03, +-4.76223201644600246940e-03, +-5.00891294846663153589e-03, +-5.25252123725567128532e-03, +-5.49292043333865411675e-03, +-5.72997603624744288736e-03, +-5.96355556960147161621e-03, +-6.19352865496984421323e-03, +-6.41976708447395284091e-03, +-6.64214489208741348802e-03, +-6.86053842359856183575e-03, +-7.07482640519247439614e-03, +-7.28489001061597037101e-03, +-7.49061292688948335977e-03, +-7.69188141852844651375e-03, +-7.88858439023906905796e-03, +-8.08061344805422777926e-03, +-8.26786295887581117181e-03, +-8.45023010839095374547e-03, +-8.62761495733049832424e-03, +-8.79992049603937377678e-03, +-8.96705269732801270310e-03, +-9.12892056757751840790e-03, +-9.28543619607121589743e-03, +-9.43651480252325272624e-03, +-9.58207478278219441925e-03, +-9.72203775268269676513e-03, +-9.85632859002284582306e-03, +-9.98487547464438525424e-03, +-1.01076099265952259326e-02, +-1.02244668423529874723e-02, +-1.03353845290914767713e-02, +-1.04403047369727476623e-02, +-1.05391726894459199226e-02, +-1.06319371115395251703e-02, +-1.07185502561315034592e-02, +-1.07989679281840673941e-02, +-1.08731495069313705004e-02, +-1.09410579660090354764e-02, +-1.10026598915155138930e-02, +-1.10579254979971536299e-02, +-1.11068286423497506604e-02, +-1.11493468356296306782e-02, +-1.11854612527701267194e-02, +-1.12151567401993432216e-02, +-1.12384218213567241285e-02, +-1.12552487001068551170e-02, +-1.12656332620508243397e-02, +-1.12695750737355805671e-02, +-1.12670773797639463265e-02, +-1.12581470978087311990e-02, +-1.12427948115352074887e-02, +-1.12210347614381672487e-02, +-1.11928848336002705749e-02, +-1.11583665463801332690e-02, +-1.11175050350392178033e-02, +-1.10703290343182984834e-02, +-1.10168708589748198801e-02, +-1.09571663822947782535e-02, +-1.08912550125919559835e-02, +-1.08191796677104181551e-02, +-1.07409867475466505593e-02, +-1.06567261046078953085e-02, +-1.05664510126258718442e-02, +-1.04702181332450312140e-02, +-1.03680874808063875486e-02, +-1.02601223852479897514e-02, +-1.01463894531454990044e-02, +-1.00269585269162232050e-02, +-9.90190264221126568989e-03, +-9.77129798352259666683e-03, +-9.63522383803080625930e-03, +-9.49376254772124616998e-03, +-9.34699945979887078518e-03, +-9.19502287542989238389e-03, +-9.03792399684144424910e-03, +-8.87579687281107691799e-03, +-8.70873834257845577667e-03, +-8.53684797821176177823e-03, +-8.36022802546492783959e-03, +-8.17898334315863943800e-03, +-7.99322134112125451399e-03, +-7.80305191672834696365e-03, +-7.60858739007534007337e-03, +-7.40994243782330200970e-03, +-7.20723402575608202564e-03, +-7.00058134008851255109e-03, +-6.79010571756536070176e-03, +-6.57593057439340850090e-03, +-6.35818133404676254922e-03, +-6.13698535398672032765e-03, +-5.91247185134246861643e-03, +-5.68477182759180490329e-03, +-5.45401799228807746683e-03, +-5.22034468587699671677e-03, +-4.98388780164810921841e-03, +-4.74478470686644573928e-03, +-4.50317416312886326102e-03, +-4.25919624599436445062e-03, +-4.01299226392974606181e-03, +-3.76470467662182433494e-03, +-3.51447701270230384446e-03, +-3.26245378693090131231e-03, +-3.00878041688648536350e-03, +-2.75360313921323108730e-03, +-2.49706892547035515587e-03, +-2.23932539763252707460e-03, +-1.98052074329282566320e-03, +-1.72080363061157654535e-03, +-1.46032312306425922019e-03, +-1.19922859403635969841e-03, +-9.37669641312056218428e-04, +-6.75796001507703134221e-04, +-4.13757464498088920954e-04, +-1.51703787884435286606e-04, + 1.10215388447121949347e-04, + 3.71850627627885114545e-04, + 6.33052780921098995522e-04, + 8.93673072601122806674e-04, + 1.15356318454689905743e-03, + 1.41257534050370911136e-03, + 1.67056238996633678491e-03, + 1.92737789163165596125e-03, + 2.18287619637864190730e-03, + 2.43691252972557228021e-03, + 2.68934307371902769912e-03, + 2.94002504820795344462e-03, + 3.18881679145808279857e-03, + 3.43557784005892952531e-03, + 3.68016900808052979666e-03, + 3.92245246543618079904e-03, + 4.16229181540278981438e-03, + 4.39955217126052674365e-03, + 4.63410023200553494727e-03, + 4.86580435709433288538e-03, + 5.09453464017795010221e-03, + 5.32016298178517119816e-03, + 5.54256316091259002704e-03, + 5.76161090548329372224e-03, + 5.97718396163549221811e-03, + 6.18916216179911122391e-03, + 6.39742749152663690154e-03, + 6.60186415503853565173e-03, + 6.80235863944797080477e-03, + 6.99879977762879034592e-03, + 7.19107880969246070213e-03, + 7.37908944304029295463e-03, + 7.56272791095595735972e-03, + 7.74189302970967625078e-03, + 7.91648625413953442587e-03, + 8.08641173168029268881e-03, + 8.25157635481136783606e-03, + 8.41188981189416006001e-03, + 8.56726463637145184415e-03, + 8.71761625430204217801e-03, + 8.86286303020573928979e-03, + 9.00292631119170398690e-03, + 9.13773046934988723844e-03, + 9.26720294237984125452e-03, + 9.39127427243598503215e-03, + 9.50987814316970984929e-03, + 9.62295141494749588229e-03, + 9.73043415822708555873e-03, + 9.83226968507381650364e-03, + 9.92840457880114421463e-03, + 1.00187887217194990935e-02, + 1.01033753209798602551e-02, + 1.01821209324982810823e-02, + 1.02549854829495166314e-02, + 1.03219322898189282134e-02, + 1.03829280795032750928e-02, + 1.04379430034503180302e-02, + 1.04869506523312169127e-02, + 1.05299280682385320435e-02, + 1.05668557549043577726e-02, + 1.05977176859349212640e-02, + 1.06225013110582688913e-02, + 1.06411975603831251286e-02, + 1.06538008466682248415e-02, + 1.06603090656027660321e-02, + 1.06607235940987827433e-02, + 1.06550492865989197139e-02, + 1.06432944694025734267e-02, + 1.06254709330158968877e-02, + 1.06015939225314811956e-02, + 1.05716821260445053426e-02, + 1.05357576611141614403e-02, + 1.04938460592794574611e-02, + 1.04459762486396531833e-02, + 1.03921805345111133156e-02, + 1.03324945781732863842e-02, + 1.02669573737173662475e-02, + 1.01956112230122235285e-02, + 1.01185017088040590805e-02, + 1.00356776659660425211e-02, + 9.94719115091608624413e-03, + 9.85309740922234687799e-03, + 9.75345484141500011777e-03, + 9.64832496702668768185e-03, + 9.53777238688333431349e-03, + 9.42186474366750112419e-03, + 9.30067268077903845647e-03, + 9.17426979951779277001e-03, + 9.04273261461393390581e-03, + 8.90614050813234511828e-03, + 8.76457568178037361994e-03, + 8.61812310764482544800e-03, + 8.46687047738961182097e-03, + 8.31090814994421903106e-03, + 8.15032909771297095491e-03, + 7.98522885133778372035e-03, + 7.81570544304719359852e-03, + 7.64185934862476878848e-03, + 7.46379342803140874429e-03, + 7.28161286471641980289e-03, + 7.09542510365326374588e-03, + 6.90533978813562872995e-03, + 6.71146869537252947074e-03, + 6.51392567091878173929e-03, + 6.31282656197840099516e-03, + 6.10828914962330098148e-03, + 5.90043307996295039036e-03, + 5.68937979430757592714e-03, + 5.47525245836473755529e-03, + 5.25817589051068290384e-03, + 5.03827648917754868096e-03, + 4.81568215940014407450e-03, + 4.59052223856344730063e-03, + 4.36292742139295433579e-03, + 4.13302968423510681123e-03, + 3.90096220866709446004e-03, + 3.66685930448303705129e-03, + 3.43085633209993298015e-03, + 3.19308962442840099660e-03, + 2.95369640825326627495e-03, + 2.71281472516826487051e-03, + 2.47058335211343968810e-03, + 2.22714172155590722779e-03, + 1.98262984136404274774e-03, + 1.73718821442020768774e-03, + 1.49095775801618085979e-03, + 1.24407972307950527406e-03, + 9.96695613276132701130e-04, + 7.48947104035837802997e-04, + 5.00975961545737855096e-04, + 2.52923961761159811490e-04, + 4.93280947509291801083e-06, +-2.42855942503384357196e-04, +-4.90300974016580110200e-04, +-7.37261278027570056415e-04, +-9.83596240843677242782e-04, +-1.22916572204938767329e-03, +-1.47383013410300081451e-03, +-1.71745052155293964798e-03, +-1.95988863982576476050e-03, +-2.20100703354622747807e-03, +-2.44066911434088866517e-03, +-2.67873923808214847372e-03, +-2.91508278153101421312e-03, +-3.14956621833333222718e-03, +-3.38205719432752276860e-03, +-3.61242460212125989991e-03, +-3.84053865489516728718e-03, +-4.06627095939203833663e-03, +-4.28949458805057831645e-03, +-4.51008415024378109953e-03, +-4.72791586258040994611e-03, +-4.94286761823193362270e-03, +-5.15481905524671577684e-03, +-5.36365162380991484375e-03, +-5.56924865241561605628e-03, +-5.77149541291191014308e-03, +-5.97027918438345836516e-03, +-6.16548931583604711143e-03, +-6.35701728764813140532e-03, +-6.54475677175619420523e-03, +-6.72860369053819660362e-03, +-6.90845627436653328401e-03, +-7.08421511779518033730e-03, +-7.25578323435132135910e-03, +-7.42306610990221913543e-03, +-7.58597175456684601896e-03, +-7.74441075314436476462e-03, +-7.89829631403181527116e-03, +-8.04754431660486060918e-03, +-8.19207335703401803850e-03, +-8.33180479251450362144e-03, +-8.46666278388312140701e-03, +-8.59657433660001440989e-03, +-8.72146934007399753097e-03, +-8.84128060530934949124e-03, +-8.95594390085470426488e-03, +-9.06539798703423320425e-03, +-9.16958464844403950411e-03, +-9.26844872469488080535e-03, +-9.36193813938749827552e-03, +-9.45000392730357963167e-03, +-9.53260025979855117606e-03, +-9.60968446838431425427e-03, +-9.68121706648877346224e-03, +-9.74716176938165805577e-03, +-9.80748551225691343747e-03, +-9.86215846646274103826e-03, +-9.91115405387120278202e-03, +-9.95444895938146258330e-03, +-9.99202314155041813881e-03, +-1.00238598413463411013e-02, +-1.00499455890222209875e-02, +-1.00702702091063772682e-02, +-1.00848268235089154332e-02, +-1.00936118527438327408e-02, +-1.00966250152679168361e-02, +-1.00938693249378146077e-02, +-1.00853510865886227682e-02, +-1.00710798897381062500e-02, +-1.00510686004214797040e-02, +-1.00253333511630630254e-02, +-9.99389352909173418749e-03, +-9.95677176220922943717e-03, +-9.91399390381976150510e-03, +-9.86558901513197826494e-03, +-9.81158934604420447656e-03, +-9.75203031412597010075e-03, +-9.68695048180868989451e-03, +-9.61639153180029321311e-03, +-9.54039824073970449403e-03, +-9.45901845110641917302e-03, +-9.37230304140389963719e-03, +-9.28030589463477509349e-03, +-9.18308386508685792204e-03, +-9.08069674345089207501e-03, +-8.97320722029071662917e-03, +-8.86068084788880529212e-03, +-8.74318600048899774446e-03, +-8.62079383296257897862e-03, +-8.49357823791978966410e-03, +-8.36161580129450403287e-03, +-8.22498575642871369851e-03, +-8.08376993668271683069e-03, +-7.93805272660061574108e-03, +-7.78792101165969724574e-03, +-7.63346412663362498818e-03, +-7.47477380259930785505e-03, +-7.31194411262098796500e-03, +-7.14507141614020412773e-03, +-6.97425430210722122754e-03, +-6.79959353088687573630e-03, +-6.62119197497169301864e-03, +-6.43915455853849138385e-03, +-6.25358819588309883253e-03, +-6.06460172876989358354e-03, +-5.87230586273140842124e-03, +-5.67681310235816811993e-03, +-5.47823768561213342299e-03, +-5.27669551720578392656e-03, +-5.07230410108449637774e-03, +-4.86518247205038317088e-03, +-4.65545112656870225393e-03, +-4.44323195279612039033e-03, +-4.22864815987201558140e-03, +-4.01182420651321949151e-03, +-3.79288572895385015307e-03, +-3.57195946827177420596e-03, +-3.34917319714373535808e-03, +-3.12465564607069309216e-03, +-2.89853642911835473334e-03, +-2.67094596921149977573e-03, +-2.44201542302870371753e-03, +-2.21187660553990271539e-03, +-1.98066191422849313675e-03, +-1.74850425304324988245e-03, +-1.51553695612283568887e-03, +-1.28189371133704578531e-03, +-1.04770848368741461600e-03, +-8.13115438614004488148e-04, +-5.78248865247532866513e-04, +-3.43243099654593679469e-04, +-1.08232448119056134180e-04, + 1.26648889498497872709e-04, + 3.61266896277643255724e-04, + 5.95487814588576617851e-04, + 8.29178222232456471966e-04, + 1.06220510832932932450e-03, + 1.29443594890761418982e-03, + 1.52573878215697851524e-03, + 1.75598228329790738422e-03, + 1.98503583902642517095e-03, + 2.21276962149356305753e-03, + 2.43905466177587538015e-03, + 2.66376292279626092005e-03, + 2.88676737165370449201e-03, + 3.10794205132203151670e-03, + 3.32716215167451348847e-03, + 3.54430407979887786632e-03, + 3.75924552955919340572e-03, + 3.97186555036659408313e-03, + 4.18204461512168643861e-03, + 4.38966468728887570377e-03, + 4.59460928706578036751e-03, + 4.79676355661041737416e-03, + 4.99601432429057183693e-03, + 5.19225016791701170921e-03, + 5.38536147692926601277e-03, + 5.57524051349589811616e-03, + 5.76178147249606278230e-03, + 5.94488054035048445189e-03, + 6.12443595266757775941e-03, + 6.30034805067354337221e-03, + 6.47251933639503632123e-03, + 6.64085452656393640525e-03, + 6.80526060521449791679e-03, + 6.96564687494400421736e-03, + 7.12192500680845601291e-03, + 7.27400908882688563423e-03, + 7.42181567306544106438e-03, + 7.56526382127895545560e-03, + 7.70427514908233069396e-03, + 7.83877386862820088598e-03, + 7.96868682976907029281e-03, + 8.09394355968027362502e-03, + 8.21447630092295155713e-03, + 8.33022004792652141780e-03, + 8.44111258187129308295e-03, + 8.54709450395172223858e-03, + 8.64810926700426002567e-03, + 8.74410320548165559407e-03, + 8.83502556375806609446e-03, + 8.92082852275120734287e-03, + 9.00146722484649296214e-03, + 9.07689979711120281669e-03, + 9.14708737278599470777e-03, + 9.21199411104400324446e-03, + 9.27158721500605589871e-03, + 9.32583694800504132971e-03, + 9.37471664808996879570e-03, + 9.41820274076340252511e-03, + 9.45627474994699748767e-03, + 9.48891530716929401668e-03, + 9.51611015897272857766e-03, + 9.53784817253677981441e-03, + 9.55412133951539892240e-03, + 9.56492477808816750351e-03, + 9.57025673322536851728e-03, + 9.57011857516825228953e-03, + 9.56451479612665210472e-03, + 9.55345300519767903769e-03, + 9.53694392150929680374e-03, + 9.51500136559463131902e-03, + 9.48764224900292864329e-03, + 9.45488656215475072042e-03, + 9.41675736044983967277e-03, + 9.37328074863657233207e-03, + 9.32448586345385396768e-03, + 9.27040485455623772260e-03, + 9.21107286373510844579e-03, + 9.14652800244862389245e-03, + 9.07681132767460333022e-03, + 9.00196681610215994340e-03, + 8.92204133667740678648e-03, + 8.83708462152045341742e-03, + 8.74714923523178117248e-03, + 8.65229054260652913344e-03, + 8.55256667477650479869e-03, + 8.44803849380110737088e-03, + 8.33876955572694297802e-03, + 8.22482607214039367072e-03, + 8.10627687023531343091e-03, + 7.98319335141973659975e-03, + 7.85564944848663425370e-03, + 7.72372158137452947957e-03, + 7.58748861154383627547e-03, + 7.44703179499617545084e-03, + 7.30243473396576317502e-03, + 7.15378332730893639474e-03, + 7.00116571962369673571e-03, + 6.84467224912835292550e-03, + 6.68439539432962807203e-03, + 6.52042971951210560688e-03, + 6.35287181908096316302e-03, + 6.18182026079089775444e-03, + 6.00737552789352719645e-03, + 5.82963996023949920094e-03, + 5.64871769436637964634e-03, + 5.46471460260989760210e-03, + 5.27773823127398664101e-03, + 5.08789773789389884046e-03, + 4.89530382763052763356e-03, + 4.70006868883239992823e-03, + 4.50230592780280144960e-03, + 4.30213050280925293073e-03, + 4.09965865737595570178e-03, + 3.89500785289395058675e-03, + 3.68829670059122758860e-03, + 3.47964489290170791991e-03, + 3.26917313427090060543e-03, + 3.05700307144005523768e-03, + 2.84325722324815094444e-03, + 2.62805890999240517047e-03, + 2.41153218238787615466e-03, + 2.19380175016706995342e-03, + 1.97499291036058082296e-03, + 1.75523147530006872613e-03, + 1.53464370038409927272e-03, + 1.31335621165009405059e-03, + 1.09149593319219089145e-03, + 8.69190014465733669022e-04, + 6.46565757523822519717e-04, + 4.23750544222993737447e-04, + 2.00871763442388796871e-04, +-2.19432616430028802536e-05, +-2.44567346193297504003e-04, +-4.66873516198418401623e-04, +-6.88735080792504629141e-04, +-9.10025704351406588243e-04, +-1.13061947832844914008e-03, +-1.35039099278848459193e-03, +-1.56921540760134731185e-03, +-1.78696852325255445618e-03, +-2.00352685123184786134e-03, +-2.21876768395961026376e-03, +-2.43256916421236753928e-03, +-2.64481035400563951540e-03, +-2.85537130289943187622e-03, +-3.06413311568427739612e-03, +-3.27097801941039290421e-03, +-3.47578942972392133937e-03, +-3.67845201647113524343e-03, +-3.87885176853450686779e-03, +-4.07687605786403312047e-03, +-4.27241370266879562367e-03, +-4.46535502973073768207e-03, +-4.65559193580989804512e-03, +-4.84301794810346793868e-03, +-5.02752828372539546653e-03, +-5.20901990817508944720e-03, +-5.38739159276095062184e-03, +-5.56254397094743408686e-03, +-5.73437959359436588702e-03, +-5.90280298305815697563e-03, +-6.06772068612327578757e-03, +-6.22904132573793255234e-03, +-6.38667565152189597305e-03, +-6.54053658902132174086e-03, +-6.69053928768123529203e-03, +-6.83660116751098716203e-03, +-6.97864196441732535098e-03, +-7.11658377417776714241e-03, +-7.25035109503333486530e-03, +-7.37987086887549603720e-03, +-7.50507252100559608954e-03, +-7.62588799844512044840e-03, +-7.74225180677637174476e-03, +-7.85410104549275414620e-03, +-7.96137544184076853537e-03, +-8.06401738313571557482e-03, +-8.16197194753211924256e-03, +-8.25518693323474758716e-03, +-8.34361288613344465048e-03, +-8.42720312584763903141e-03, +-8.50591377016694447089e-03, +-8.57970375787523234501e-03, +-8.64853486994612667693e-03, +-8.71237174909944220302e-03, +-8.77118191770899502391e-03, +-8.82493579405169495389e-03, +-8.87360670689150109192e-03, +-8.91717090839015333326e-03, +-8.95560758533894135658e-03, +-8.98889886870667467744e-03, +-9.01702984149947012193e-03, +-9.03998854492910064451e-03, +-9.05776598288827831940e-03, +-9.07035612473096330977e-03, +-9.07775590635802147321e-03, +-9.07996522960853764961e-03, +-9.07698695995886803423e-03, +-9.06882692253164167384e-03, +-9.05549389641891432079e-03, +-9.03699960732328583246e-03, +-9.01335871852335275556e-03, +-8.98458882016932476600e-03, +-8.95071041691646723804e-03, +-8.91174691390494294607e-03, +-8.86772460109508213477e-03, +-8.81867263596835572470e-03, +-8.76462302460546613392e-03, +-8.70561060115330326292e-03, +-8.64167300569398770527e-03, +-8.57285066052993274810e-03, +-8.49918674489946214534e-03, +-8.42072716813898301813e-03, +-8.33752054130776007468e-03, +-8.24961814729350748077e-03, +-8.15707390941654633676e-03, +-8.05994435855085684939e-03, +-7.95828859878412557538e-03, +-7.85216827163510294740e-03, +-7.74164751885155454081e-03, +-7.62679294381024292654e-03, +-7.50767357154260520785e-03, +-7.38436080740939235212e-03, +-7.25692839445000407311e-03, +-7.12545236943096498700e-03, +-6.99001101761916477512e-03, +-6.85068482630888687945e-03, +-6.70755643712759620778e-03, +-6.56071059715018171238e-03, +-6.41023410885009203158e-03, +-6.25621577891687877943e-03, +-6.09874636596976875402e-03, +-5.93791852719933836713e-03, +-5.77382676396723509143e-03, +-5.60656736639539039074e-03, +-5.43623835697979850695e-03, +-5.26293943325864543858e-03, +-5.08677190957020682743e-03, +-4.90783865793382578085e-03, +-4.72624404808862780270e-03, +-4.54209388672411652765e-03, +-4.35549535594014370493e-03, +-4.16655695096843255165e-03, +-3.97538841719484881826e-03, +-3.78210068651828800954e-03, +-3.58680581308160571774e-03, +-3.38961690841329795279e-03, +-3.19064807601676572041e-03, +-2.99001434544510355171e-03, +-2.78783160589872848825e-03, +-2.58421653938650406832e-03, +-2.37928655348473936521e-03, +-2.17315971373707597994e-03, +-1.96595467573080053339e-03, +-1.75779061689126871355e-03, +-1.54878716803180682161e-03, +-1.33906434469759582327e-03, +-1.12874247834651849839e-03, +-9.17942147402158120997e-04, +-7.06784108220954348026e-04, +-4.95389226012176797989e-04, +-2.83878405750408527308e-04, +-7.23725231191953317922e-05, + 1.39007644472942073393e-04, + 3.50141486766494293426e-04, + 5.60908629376450848514e-04, + 7.71189002326557382014e-04, + 9.80862908357632698117e-04, + 1.18981109096850837074e-03, + 1.39791480215185285468e-03, + 1.60505586978618446266e-03, + 1.81111676464667430489e-03, + 2.01598066699498323223e-03, + 2.21953153271216372527e-03, + 2.42165415893787249260e-03, + 2.62223424917535025483e-03, + 2.82115847782954658890e-03, + 3.01831455413943379809e-03, + 3.21359128546936040696e-03, + 3.40687863992359188381e-03, + 3.59806780824958004350e-03, + 3.78705126499338838933e-03, + 3.97372282887472824675e-03, + 4.15797772234820922632e-03, + 4.33971263031428678564e-03, + 4.51882575795083032272e-03, + 4.69521688763073485884e-03, + 4.86878743489439942682e-03, + 5.03944050344600283364e-03, + 5.20708093914320439138e-03, + 5.37161538294856407555e-03, + 5.53295232281637763133e-03, + 5.69100214448343532520e-03, + 5.84567718113605111485e-03, + 5.99689176192734485493e-03, + 6.14456225931638965604e-03, + 6.28860713520388876080e-03, + 6.42894698583886935878e-03, + 6.56550458547169348000e-03, + 6.69820492872941122137e-03, + 6.82697527169041310652e-03, + 6.95174517163579808177e-03, + 7.07244652545614607003e-03, + 7.18901360669207869364e-03, + 7.30138310118917405883e-03, + 7.40949414134865064208e-03, + 7.51328833895314410901e-03, + 7.61270981655247976766e-03, + 7.70770523739102830091e-03, + 7.79822383386149457080e-03, + 7.88421743446952177914e-03, + 7.96564048929547866007e-03, + 8.04245009393938191378e-03, + 8.11460601193707622980e-03, + 8.18207069563602756856e-03, + 8.24480930551941583462e-03, + 8.30278972796945347046e-03, + 8.35598259146062144476e-03, + 8.40436128117489321399e-03, + 8.44790195203182735229e-03, + 8.48658354012752670636e-03, + 8.52038777257667530318e-03, + 8.54929917575385743544e-03, + 8.57330508193055763899e-03, + 8.59239563430499141139e-03, + 8.60656379042347950692e-03, + 8.61580532399272396027e-03, + 8.62011882508288869442e-03, + 8.61950569872288463458e-03, + 8.61397016188992017960e-03, + 8.60351923889614116081e-03, + 8.58816275517627555902e-03, + 8.56791332948142643489e-03, + 8.54278636448400040260e-03, + 8.51280003580121708007e-03, + 8.47797527944401177469e-03, + 8.43833577770019410691e-03, + 8.39390794346085364341e-03, + 8.34472090300016587638e-03, + 8.29080647722033568792e-03, + 8.23219916137209704876e-03, + 8.16893610326531807719e-03, + 8.10105707998175217366e-03, + 8.02860447310570039814e-03, + 7.95162324248711339936e-03, + 7.87016089855287724608e-03, + 7.78426747318477444543e-03, + 7.69399548918007353260e-03, + 7.59939992831438169973e-03, + 7.50053819802581206444e-03, + 7.39747009674054673695e-03, + 7.29025777786024634097e-03, + 7.17896571243396234424e-03, + 7.06366065053597690093e-03, + 6.94441158137212768281e-03, + 6.82128969214047548714e-03, + 6.69436832566827795532e-03, + 6.56372293685217843284e-03, + 6.42943104792645641482e-03, + 6.29157220258638738564e-03, + 6.15022791899296188828e-03, + 6.00548164168810023889e-03, + 5.85741869244729099903e-03, + 5.70612622009830997016e-03, + 5.55169314933761943315e-03, + 5.39421012857201238877e-03, + 5.23376947681718652367e-03, + 5.07046512968433327889e-03, + 4.90439258448602602436e-03, + 4.73564884449306690989e-03, + 4.56433236237605791802e-03, + 4.39054298286334701573e-03, + 4.21438188464811746420e-03, + 4.03595152158122121716e-03, + 3.85535556318054341285e-03, + 3.67269883449336575001e-03, + 3.48808725534603724164e-03, + 3.30162777901616766654e-03, + 3.11342833036215701700e-03, + 2.92359774344746591729e-03, + 2.73224569869404739636e-03, + 2.53948265960054347934e-03, + 2.34541980906500472509e-03, + 2.15016898534491464681e-03, + 1.95384261769374848600e-03, + 1.75655366171025071990e-03, + 1.55841553443768969338e-03, + 1.35954204925029724198e-03, + 1.16004735056427139318e-03, + 9.60045848410695946279e-04, + 7.59652152908002432571e-04, + 5.58981008670681638398e-04, + 3.58147229193453995114e-04, + 1.57265631246792758451e-04, +-4.35490306794674293363e-05, +-2.44182129843599320107e-04, +-4.44519232597282950344e-04, +-6.44446163569028346828e-04, +-8.43849070649477944230e-04, +-1.04261448974139812711e-03, +-1.24062940923833162771e-03, +-1.43778133419359788019e-03, +-1.63395835014485757766e-03, +-1.82904918655875121242e-03, +-2.02294327985625636140e-03, +-2.21553083598718210043e-03, +-2.40670289251588859908e-03, +-2.59635138018404895352e-03, +-2.78436918391547104032e-03, +-2.97065020322924595864e-03, +-3.15508941202569071979e-03, +-3.33758291771281195501e-03, +-3.51802801964081748518e-03, +-3.69632326680855837625e-03, +-3.87236851481334142661e-03, +-4.04606498200982094005e-03, +-4.21731530484743474818e-03, +-4.38602359235502371748e-03, +-4.55209547974291459105e-03, +-4.71543818109126672972e-03, +-4.87596054109631048268e-03, +-5.03357308584660798761e-03, +-5.18818807259795525266e-03, +-5.33971953852289266118e-03, +-5.48808334840551401146e-03, +-5.63319724125592186798e-03, +-5.77498087581854776390e-03, +-5.91335587494941708475e-03, +-6.04824586883698656764e-03, +-6.17957653704386423305e-03, +-6.30727564934618813858e-03, +-6.43127310534771529787e-03, +-6.55150097284682483151e-03, +-6.66789352493667251270e-03, +-6.78038727581722639598e-03, +-6.88892101529996712939e-03, +-6.99343584198691605586e-03, +-7.09387519510564119873e-03, +-7.19018488498349497839e-03, +-7.28231312214434444580e-03, +-7.37021054501293959582e-03, +-7.45383024621102448920e-03, +-7.53312779743236203556e-03, +-7.60806127288360129618e-03, +-7.67859127127740528906e-03, +-7.74468093636805719054e-03, +-7.80629597601776963056e-03, +-7.86340467978466871324e-03, +-7.91597793502309132752e-03, +-7.96398924148845367699e-03, +-8.00741472443937570003e-03, +-8.04623314623062815820e-03, +-8.08042591639200093179e-03, +-8.10997710018770794071e-03, +-8.13487342565317322896e-03, +-8.15510428910632897970e-03, +-8.17066175913122756669e-03, +-8.18154057903300313548e-03, +-8.18773816776408903950e-03, +-8.18925461932203113680e-03, +-8.18609270062076350982e-03, +-8.17825784783763644337e-03, +-8.16575816123921681411e-03, +-8.14860439849041627569e-03, +-8.12680996645165354408e-03, +-8.10039091146990027081e-03, +-8.06936590817051296876e-03, +-8.03375624675719754442e-03, +-7.99358581882871586932e-03, +-7.94888110172140179011e-03, +-7.89967114138754450403e-03, +-7.84598753382080051078e-03, +-7.78786440504017178632e-03, +-7.72533838964500462615e-03, +-7.65844860795453739877e-03, +-7.58723664174604933708e-03, +-7.51174650860678399383e-03, +-7.43202463491451133931e-03, +-7.34811982746492921986e-03, +-7.26008324376091473962e-03, +-7.16796836098336151433e-03, +-7.07183094366188418067e-03, +-6.97172901006430818793e-03, +-6.86772279732582834055e-03, +-6.75987472533817052023e-03, +-6.64824935942080145340e-03, +-6.53291337179604837682e-03, +-6.41393550189129496575e-03, +-6.29138651549170698635e-03, +-6.16533916276751359220e-03, +-6.03586813520128485228e-03, +-5.90305002144024624361e-03, +-5.76696326209861012679e-03, +-5.62768810353925751089e-03, +-5.48530655065889230504e-03, +-5.33990231870646887141e-03, +-5.19156078416207946574e-03, +-5.04036893470575456805e-03, +-4.88641531830454143442e-03, +-4.72978999144895145140e-03, +-4.57058446656796041330e-03, +-4.40889165865240156839e-03, +-4.24480583112071818697e-03, +-4.07842254095536725644e-03, +-3.90983858314355049030e-03, +-3.73915193445415730208e-03, +-3.56646169658344580969e-03, +-3.39186803870199487382e-03, +-3.21547213943741911138e-03, +-3.03737612832535950474e-03, +-2.85768302676162435152e-03, +-2.67649668849279489050e-03, +-2.49392173967607306759e-03, +-2.31006351854499665868e-03, +-2.12502801471515026521e-03, +-1.93892180816497236052e-03, +-1.75185200792604364207e-03, +-1.56392619051968551937e-03, +-1.37525233817362515544e-03, +-1.18593877685428585739e-03, +-9.96094114151082135611e-04, +-8.05827177048465143755e-04, +-6.15246949619699455385e-04, +-4.24462510679590970634e-04, +-2.33582971431131201836e-04, +-4.27174131418600218075e-05, + 1.48025175115281873829e-04, + 3.38535958618741729398e-04, + 5.28706319021235741570e-04, + 7.18427916200129542020e-04, + 9.07592749900823655106e-04, + 1.09609322113959862730e-03, + 1.28382219332944988964e-03, + 1.47067305309492128707e-03, + 1.65653977074134688835e-03, + 1.84131696034424701021e-03, + 2.02489993942486920173e-03, + 2.20718478817801639844e-03, + 2.38806840821935862512e-03, + 2.56744858081750862433e-03, + 2.74522402457949956170e-03, + 2.92129445255769277026e-03, + 3.09556062874293989526e-03, + 3.26792442391583577016e-03, + 3.43828887082240275061e-03, + 3.60655821864397721499e-03, + 3.77263798673060360075e-03, + 3.93643501756839753886e-03, + 4.09785752894968862553e-03, + 4.25681516531844095913e-03, + 4.41321904826232503521e-03, + 4.56698182612100180705e-03, + 4.71801772268583795300e-03, + 4.86624258496219565945e-03, + 5.01157392996826912823e-03, + 5.15393099054442353768e-03, + 5.29323476014809113366e-03, + 5.42940803660817671028e-03, + 5.56237546481617214228e-03, + 5.69206357833054472223e-03, + 5.81840083986934729354e-03, + 5.94131768067147035539e-03, + 6.06074653870333594774e-03, + 6.17662189569052801769e-03, + 6.28888031295409682953e-03, + 6.39746046603201657527e-03, + 6.50230317806734740144e-03, + 6.60335145194352116094e-03, + 6.70055050115188084031e-03, + 6.79384777937258772795e-03, + 6.88319300875362728720e-03, + 6.96853820687349644752e-03, + 7.04983771237240302437e-03, + 7.12704820923858520243e-03, + 7.20012874973695923136e-03, + 7.26904077596829921448e-03, + 7.33374814004676342516e-03, + 7.39421712288685674397e-03, + 7.45041645158874780291e-03, + 7.50231731541360375576e-03, + 7.54989338034125958415e-03, + 7.59312080220247119511e-03, + 7.63197823837959577614e-03, + 7.66644685807015349721e-03, + 7.69651035110831445440e-03, + 7.72215493534070089587e-03, + 7.74336936255298931286e-03, + 7.76014492294555859042e-03, + 7.77247544815607566138e-03, + 7.78035731282916958457e-03, + 7.78378943473276123377e-03, + 7.78277327342252397968e-03, + 7.77731282745607217788e-03, + 7.76741463015983343160e-03, + 7.75308774395181993927e-03, + 7.73434375322510497819e-03, + 7.71119675579651046859e-03, + 7.68366335292724762090e-03, + 7.65176263792180597761e-03, + 7.61551618331250072119e-03, + 7.57494802663899804984e-03, + 7.53008465483087727904e-03, + 7.48095498720392076963e-03, + 7.42759035708089564165e-03, + 7.37002449204788440129e-03, + 7.30829349285897541394e-03, + 7.24243581100231150621e-03, + 7.17249222494118019583e-03, + 7.09850581504455676457e-03, + 7.02052193722279248289e-03, + 6.93858819528464596665e-03, + 6.85275441203157895803e-03, + 6.76307259910770459943e-03, + 6.66959692562291064227e-03, + 6.57238368556857608521e-03, + 6.47149126404455293793e-03, + 6.36698010231910756229e-03, + 6.25891266174058436000e-03, + 6.14735338652398939641e-03, + 6.03236866543420662684e-03, + 5.91402679238786036647e-03, + 5.79239792599798089534e-03, + 5.66755404808486160789e-03, + 5.53956892117803134656e-03, + 5.40851804503346585140e-03, + 5.27447861219351547823e-03, + 5.13752946261299917735e-03, + 4.99775103738003996512e-03, + 4.85522533155877469846e-03, + 4.71003584618005094464e-03, + 4.56226753940958736772e-03, + 4.41200677692144428016e-03, + 4.25934128150591128498e-03, + 4.10436008194120516279e-03, + 3.94715346115854636561e-03, + 3.78781290373112009690e-03, + 3.62643104271654281509e-03, + 3.46310160588530037765e-03, + 3.29791936136483157180e-03, + 3.13098006273033763885e-03, + 2.96238039357679455374e-03, + 2.79221791160092977502e-03, + 2.62059099222753267427e-03, + 2.44759877181191781020e-03, + 2.27334109045146740002e-03, + 2.09791843443869838876e-03, + 1.92143187839023546828e-03, + 1.74398302708383490592e-03, + 1.56567395703608109106e-03, + 1.38660715785749919481e-03, + 1.20688547341501702971e-03, + 1.02661204283784578128e-03, + 8.45890241399772859106e-04, + 6.64823621311828307986e-04, + 4.83515852459311156267e-04, + 3.02070663116303390200e-04, + 1.20591780673772898239e-04, +-6.08171275885414341889e-05, +-2.42052513649585246663e-04, +-4.23011007780704729672e-04, +-6.03589477433417857279e-04, +-7.83685085946226591899e-04, +-9.63195351037734169043e-04, +-1.14201820305262708236e-03, +-1.32005204292819870032e-03, +-1.49719579984629639312e-03, +-1.67334898854166894480e-03, +-1.84841176623110319682e-03, +-2.02228498913186371597e-03, +-2.19487026853879690913e-03, +-2.36607002642698479797e-03, +-2.53578755054913694555e-03, +-2.70392704899653085748e-03, +-2.87039370419339950197e-03, +-3.03509372629227804768e-03, +-3.19793440594374599878e-03, +-3.35882416640786475581e-03, +-3.51767261497890407207e-03, +-3.67439059369556366569e-03, +-3.82889022930704356340e-03, +-3.98108498246762219919e-03, +-4.13088969613195546721e-03, +-4.27822064312436464023e-03, +-4.42299557285530213491e-03, +-4.56513375715911651903e-03, +-4.70455603522795286209e-03, +-4.84118485761577625054e-03, +-4.97494432928909796621e-03, +-5.10576025170110612411e-03, +-5.23356016386354247483e-03, +-5.35827338239640901113e-03, +-5.47983104053158340957e-03, +-5.59816612604972611844e-03, +-5.71321351812927209768e-03, +-5.82491002308763421852e-03, +-5.93319440899438971249e-03, +-6.03800743913827410447e-03, +-6.13929190432966741947e-03, +-6.23699265402067378611e-03, +-6.33105662622569179826e-03, +-6.42143287622725950775e-03, +-6.50807260405082601412e-03, +-6.59092918069416680571e-03, +-6.66995817309711056670e-03, +-6.74511736783881075269e-03, +-6.81636679354884200688e-03, +-6.88366874202207389838e-03, +-6.94698778802482330014e-03, +-7.00629080778204620106e-03, +-7.06154699613719197271e-03, +-7.11272788237445920123e-03, +-7.15980734469658271213e-03, +-7.20276162335014690646e-03, +-7.24156933239256637991e-03, +-7.27621147009427024499e-03, +-7.30667142797224253986e-03, +-7.33293499844991664843e-03, +-7.35499038114030730118e-03, +-7.37282818775028547797e-03, +-7.38644144560350775219e-03, +-7.39582559978183007310e-03, +-7.40097851388428658315e-03, +-7.40190046940486859328e-03, +-7.39859416373013153989e-03, +-7.39106470675889026811e-03, +-7.37931961614715723613e-03, +-7.36336881118193880419e-03, +-7.34322460528822728437e-03, +-7.31890169717512584224e-03, +-7.29041716062642924934e-03, +-7.25779043294308163353e-03, +-7.22104330204492456807e-03, +-7.18019989224008559070e-03, +-7.13528664867118991161e-03, +-7.08633232044840466468e-03, +-7.03336794247966679700e-03, +-6.97642681600977102030e-03, +-6.91554448788011654620e-03, +-6.85075872852217854225e-03, +-6.78210950869807035341e-03, +-6.70963897500246285455e-03, +-6.63339142414092006877e-03, +-6.55341327599992442415e-03, +-6.46975304552541326253e-03, +-6.38246131342605754061e-03, +-6.29159069572002467574e-03, +-6.19719581214200551655e-03, +-6.09933325343054149464e-03, +-5.99806154751515805540e-03, +-5.89344112462262485069e-03, +-5.78553428132379601867e-03, +-5.67440514354219504439e-03, +-5.56011962854616095114e-03, +-5.44274540594681839611e-03, +-5.32235185772599213305e-03, +-5.19901003731562585258e-03, +-5.07279262775460568907e-03, +-4.94377389894712446911e-03, +-4.81202966404692660668e-03, +-4.67763723499383179960e-03, +-4.54067537722822531232e-03, +-4.40122426361012723806e-03, +-4.25936542756916083213e-03, +-4.11518171551450429035e-03, +-3.96875723852973399941e-03, +-3.82017732338308995885e-03, +-3.66952846288120431220e-03, +-3.51689826559387639163e-03, +-3.36237540498054293669e-03, +-3.20604956794714058416e-03, +-3.04801140286350535219e-03, +-2.88835246707072135566e-03, +-2.72716517391074315599e-03, +-2.56454273930563836012e-03, +-2.40057912792011364511e-03, +-2.23536899893777120732e-03, +-2.06900765148108206626e-03, +-1.90159096970791930900e-03, +-1.73321536761559679037e-03, +-1.56397773358425175305e-03, +-1.39397537469151283109e-03, +-1.22330596083027954082e-03, +-1.05206746866192031586e-03, +-8.80358125436270775623e-04, +-7.08276352712239277640e-04, +-5.35920710009009110958e-04, +-3.63389838422367814508e-04, +-1.90782404235573607330e-04, +-1.81970425606722737690e-05, + 1.54267698961177570456e-04, + 3.26513416366015622218e-04, + 4.98441905449340362869e-04, + 6.69955217690751999443e-04, + 8.40955715991319185942e-04, + 1.01134613018985628115e-03, + 1.18102961232867528438e-03, + 1.34990979163519928159e-03, + 1.51789082919096310863e-03, + 1.68487747225296133520e-03, + 1.85077510820205867401e-03, + 2.01548981808303672575e-03, + 2.17892842970867023702e-03, + 2.34099857029698189825e-03, + 2.50160871861258458579e-03, + 2.66066825658141034583e-03, + 2.81808752035150444221e-03, + 2.97377785076984252691e-03, + 3.12765164324742489868e-03, + 3.27962239698395725818e-03, + 3.42960476352574062178e-03, + 3.57751459462877022255e-03, + 3.72326898939903325192e-03, + 3.86678634068614995867e-03, + 4.00798638070307827741e-03, + 4.14679022584586980810e-03, + 4.28312042068948461981e-03, + 4.41690098113505479061e-03, + 4.54805743668363141041e-03, + 4.67651687181444911112e-03, + 4.80220796644356944655e-03, + 4.92506103544097621760e-03, + 5.04500806718418456226e-03, + 5.16198276112742483052e-03, + 5.27592056436465041414e-03, + 5.38675870716774727459e-03, + 5.49443623747928808210e-03, + 5.59889405434115926957e-03, + 5.70007494024133646443e-03, + 5.79792359236085651231e-03, + 5.89238665270259628914e-03, + 5.98341273708859113650e-03, + 6.07095246300716831489e-03, + 6.15495847629641840842e-03, + 6.23538547664926560282e-03, + 6.31219024192670834228e-03, + 6.38533165126559023456e-03, + 6.45477070696955871482e-03, + 6.52047055517085416554e-03, + 6.58239650525249079399e-03, + 6.64051604802040618125e-03, + 6.69479887261659797199e-03, + 6.74521688216371366476e-03, + 6.79174420813415374160e-03, + 6.83435722343555315111e-03, + 6.87303455420689574096e-03, + 6.90775709031867489462e-03, + 6.93850799457300902728e-03, + 6.96527271059846700418e-03, + 6.98803896943703088673e-03, + 7.00679679481976212113e-03, + 7.02153850712936879186e-03, + 7.03225872604836682589e-03, + 7.03895437189253850990e-03, + 7.04162466562946627591e-03, + 7.04027112758361280076e-03, + 7.03489757482926060528e-03, + 7.02551011727416043623e-03, + 7.01211715243688429866e-03, + 6.99472935892183310391e-03, + 6.97335968859667636177e-03, + 6.94802335747783921666e-03, + 6.91873783532993662237e-03, + 6.88552283398612303966e-03, + 6.84840029439715090170e-03, + 6.80739437241735696749e-03, + 6.76253142333664569730e-03, + 6.71383998516838706450e-03, + 6.66135076070345499843e-03, + 6.60509659834187211336e-03, + 6.54511247171371459558e-03, + 6.48143545810195200602e-03, + 6.41410471568024109779e-03, + 6.34316145958003368976e-03, + 6.26864893680093449718e-03, + 6.19061239997995525763e-03, + 6.10909908003542511529e-03, + 6.02415815770170753884e-03, + 5.93584073397201983369e-03, + 5.84419979946794454495e-03, + 5.74929020275181338478e-03, + 5.65116861760294342948e-03, + 5.54989350927625503529e-03, + 5.44552509976333788677e-03, + 5.33812533207639414862e-03, + 5.22775783357706802512e-03, + 5.11448787837056554478e-03, + 4.99838234878814680062e-03, + 4.87950969598033648666e-03, + 4.75793989964418302663e-03, + 4.63374442690764765801e-03, + 4.50699619039651548646e-03, + 4.37776950550668349227e-03, + 4.24614004690850900536e-03, + 4.11218480430692711475e-03, + 3.97598203748505876071e-03, + 3.83761123065512682953e-03, + 3.69715304614688265381e-03, + 3.55468927745570878116e-03, + 3.41030280168198429019e-03, + 3.26407753138687091454e-03, + 3.11609836589335845169e-03, + 2.96645114206062080267e-03, + 2.81522258455971620753e-03, + 2.66250025568077076238e-03, + 2.50837250469876198167e-03, + 2.35292841682855887256e-03, + 2.19625776179852754202e-03, + 2.03845094207133958539e-03, + 1.87959894074250246331e-03, + 1.71979326914796590980e-03, + 1.55912591420826569452e-03, + 1.39768928554081183456e-03, + 1.23557616237141834267e-03, + 1.07287964027444793387e-03, + 9.09693077772073983855e-04, + 7.46110042824598817396e-04, + 5.82224259240568249411e-04, + 4.18129553038750639577e-04, + 2.53919798792089188456e-04, + 8.96888659844675517445e-05, +-7.44694345896905772258e-05, +-2.38461404350935065157e-04, +-4.02193510356873369562e-04, +-5.65572438589027263849e-04, +-7.28505147074144480956e-04, +-8.90898918810926966801e-04, +-1.05266141447140325338e-03, +-1.21370072484502889917e-03, +-1.37392542300045520862e-03, +-1.53324461613069552152e-03, +-1.69156799705494180486e-03, +-1.84880589534694829770e-03, +-2.00486932806183924816e-03, +-2.15967005003114657924e-03, +-2.31312060369968800280e-03, +-2.46513436847466778021e-03, +-2.61562560955978882365e-03, +-2.76450952624671683969e-03, +-2.91170229963722427408e-03, +-3.05712113976792237979e-03, +-3.20068433211290236454e-03, +-3.34231128343639950426e-03, +-3.48192256697167851556e-03, +-3.61943996689886252766e-03, +-3.75478652209826086611e-03, +-3.88788656915454566149e-03, +-4.01866578458679943320e-03, +-4.14705122628237707327e-03, +-4.27297137411052248279e-03, +-4.39635616969335368820e-03, +-4.51713705531228693069e-03, +-4.63524701192860166116e-03, +-4.75062059629599835880e-03, +-4.86319397714623982004e-03, +-4.97290497042671315875e-03, +-5.07969307357067009767e-03, +-5.18349949878208187543e-03, +-5.28426720531614563942e-03, +-5.38194093073713492048e-03, +-5.47646722113816729338e-03, +-5.56779446030545265012e-03, +-5.65587289781075818612e-03, +-5.74065467601772051742e-03, +-5.82209385598695533526e-03, +-5.90014644226589859283e-03, +-5.97477040655035752242e-03, +-6.04592571020508891960e-03, +-6.11357432563106647366e-03, +-6.17768025646842598719e-03, +-6.23820955662453009022e-03, +-6.29513034811653680867e-03, +-6.34841283772002301644e-03, +-6.39802933241444878737e-03, +-6.44395425361771970879e-03, +-6.48616415020282759824e-03, +-6.52463771028981894679e-03, +-6.55935577180693108607e-03, +-6.59030133181688366345e-03, +-6.61745955460281767846e-03, +-6.64081777851058003420e-03, +-6.66036552154464483316e-03, +-6.67609448571504417863e-03, +-6.68799856013396580579e-03, +-6.69607382286100619867e-03, +-6.70031854149736628978e-03, +-6.70073317252893423113e-03, +-6.69732035942032649656e-03, +-6.69008492946125080808e-03, +-6.67903388936833767447e-03, +-6.66417641964580503844e-03, +-6.64552386770900921364e-03, +-6.62308973977570117353e-03, +-6.59688969153084895508e-03, +-6.56694151757089734922e-03, +-6.53326513963461280587e-03, +-6.49588259362816715370e-03, +-6.45481801545267231540e-03, +-6.41009762564318658074e-03, +-6.36174971282886698998e-03, +-6.30980461602472040422e-03, +-6.25429470576554895345e-03, +-6.19525436409436129626e-03, +-6.13271996341689488996e-03, +-6.06672984423554158967e-03, +-5.99732429177634272788e-03, +-5.92454551152269380532e-03, +-5.84843760367088558172e-03, +-5.76904653652344102249e-03, +-5.68642011883526560245e-03, +-5.60060797112928252656e-03, +-5.51166149599965557448e-03, +-5.41963384741940817219e-03, +-5.32457989907073915570e-03, +-5.22655621171772520606e-03, +-5.12562099963942419123e-03, +-5.02183409614448406089e-03, +-4.91525691818681109702e-03, +-4.80595243010374650883e-03, +-4.69398510649735815209e-03, +-4.57942089428194781808e-03, +-4.46232717391857429401e-03, +-4.34277271986037178425e-03, +-4.22082766023175893350e-03, +-4.09656343576443940369e-03, +-3.97005275801442028549e-03, +-3.84136956688634241541e-03, +-3.71058898748600606704e-03, +-3.57778728632999511172e-03, +-3.44304182693580453772e-03, +-3.30643102481900002035e-03, +-3.16803430192340654270e-03, +-3.02793204051044796687e-03, +-2.88620553653542132044e-03, +-2.74293695253627518860e-03, +-2.59820927006318425079e-03, +-2.45210624167601677625e-03, +-2.30471234253809770590e-03, +-2.15611272163192388071e-03, +-2.00639315262918054017e-03, +-1.85563998443917131317e-03, +-1.70394009146592178422e-03, +-1.55138082360318694218e-03, +-1.39804995599510811267e-03, +-1.24403563859131600054e-03, +-1.08942634552675727232e-03, +-9.34310824353430722893e-04, +-7.78778045154488265424e-04, +-6.22917149569355557345e-04, +-4.66817399759168381000e-04, +-3.10568127341177748629e-04, +-1.54258682322715390484e-04, + 2.02161793800758804308e-06, + 1.58183539713823383393e-04, + 3.14137983804192602675e-04, + 4.69796036316565991924e-04, + 6.25069019303870366394e-04, + 7.79868541228004980535e-04, + 9.34106547223279145772e-04, + 1.08769536912991875675e-03, + 1.24054777526851588154e-03, + 1.39257701992830692887e-03, + 1.54369689254121996921e-03, + 1.69382176651257680342e-03, + 1.84286664768265498297e-03, + 1.99074722239030730067e-03, + 2.13737990511212458747e-03, + 2.28268188564996954079e-03, + 2.42657117584086636994e-03, + 2.56896665576163141242e-03, + 2.70978811940393539068e-03, + 2.84895631979290410787e-03, + 2.98639301352399176917e-03, + 3.12202100469403682342e-03, + 3.25576418820130086482e-03, + 3.38754759238860721909e-03, + 3.51729742100961384824e-03, + 3.64494109449081107530e-03, + 3.77040729046844522859e-03, + 3.89362598357706262905e-03, + 4.01452848446753798178e-03, + 4.13304747803329777800e-03, + 4.24911706082250345551e-03, + 4.36267277761673982761e-03, + 4.47365165715500091859e-03, + 4.58199224698366443242e-03, + 4.68763464741256234702e-03, + 4.79052054456022714107e-03, + 4.89059324246701558614e-03, + 4.98779769426149852812e-03, + 5.08208053236177022260e-03, + 5.17339009769468647498e-03, + 5.26167646791786663280e-03, + 5.34689148462896227804e-03, + 5.42898877954677526458e-03, + 5.50792379965109931556e-03, + 5.58365383126675513675e-03, + 5.65613802307947735604e-03, + 5.72533740807081026336e-03, + 5.79121492436091966222e-03, + 5.85373543494751170241e-03, + 5.91286574633094908632e-03, + 5.96857462601572963390e-03, + 6.02083281887862576537e-03, + 6.06961306239588074124e-03, + 6.11489010072096151466e-03, + 6.15664069760550429489e-03, + 6.19484364815777593938e-03, + 6.22947978943221101350e-03, + 6.26053200984478218361e-03, + 6.28798525741010132240e-03, + 6.31182654679610100068e-03, + 6.33204496519319988412e-03, + 6.34863167699579490633e-03, + 6.36157992729387798680e-03, + 6.37088504417378069522e-03, + 6.37654443982793583956e-03, + 6.37855761047346776077e-03, + 6.37692613508076319023e-03, + 6.37165367291377907760e-03, + 6.36274595988404155500e-03, + 6.35021080372164415523e-03, + 6.33405807796656641212e-03, + 6.31429971478498618803e-03, + 6.29094969661516800058e-03, + 6.26402404664898240089e-03, + 6.23354081815498742292e-03, + 6.19952008265027120631e-03, + 6.16198391692862612601e-03, + 6.12095638895326834422e-03, + 6.07646354262293339477e-03, + 6.02853338142123572341e-03, + 5.97719585095891989962e-03, + 5.92248282042035986694e-03, + 5.86442806292514912103e-03, + 5.80306723481761356498e-03, + 5.73843785389547937636e-03, + 5.67057927659296145267e-03, + 5.59953267413014401516e-03, + 5.52534100764390679467e-03, + 5.44804900231556955836e-03, + 5.36770312051036008194e-03, + 5.28435153394469885046e-03, + 5.19804409489867894761e-03, + 5.10883230648978472338e-03, + 5.01676929202641425087e-03, + 4.92190976345897174271e-03, + 4.82430998894739331007e-03, + 4.72402775956395210022e-03, + 4.62112235515180647810e-03, + 4.51565450935827780027e-03, + 4.40768637386434840308e-03, + 4.29728148183127715148e-03, + 4.18450471058511973971e-03, + 4.06942224356152213588e-03, + 3.95210153153399603582e-03, + 3.83261125314650298243e-03, + 3.71102127477429544200e-03, + 3.58740260973707415088e-03, + 3.46182737688722997824e-03, + 3.33436875859757829790e-03, + 3.20510095817370162935e-03, + 3.07409915671442122986e-03, + 2.94143946944645578653e-03, + 2.80719890155818000560e-03, + 2.67145530355801606032e-03, + 2.53428732618405597871e-03, + 2.39577437488870843840e-03, + 2.25599656392876232389e-03, + 2.11503467008288762591e-03, + 1.97297008602663600726e-03, + 1.82988477338951447716e-03, + 1.68586121552325774765e-03, + 1.54098237000600303548e-03, + 1.39533162091338329772e-03, + 1.24899273087909832951e-03, + 1.10204979297680240487e-03, + 9.54587182448630219150e-04, + 8.06689508308766145897e-04, + 6.58441564849216722996e-04, + 5.09928283076855021032e-04, + 3.61234682107735086132e-04, + 2.12445820547849437534e-04, + 6.36467478874062951924e-05, +-8.50775440627651754989e-05, +-2.33642169667408998316e-04, +-3.81962397863639291536e-04, +-5.29953700435123313019e-04, +-6.77531800134304070492e-04, +-8.24612718624688793498e-04, +-9.71112824217015813653e-04, +-1.11694887937219939321e-03, +-1.26203808794284771423e-03, +-1.40629814212836251781e-03, +-1.54964726911566716763e-03, +-1.69200427737972594958e-03, +-1.83328860261746241604e-03, +-1.97342035328964800558e-03, +-2.11232035574377557952e-03, +-2.24991019889414630914e-03, +-2.38611227843281599459e-03, +-2.52084984054647175469e-03, +-2.65404702511572903115e-03, +-2.78562890837174507302e-03, +-2.91552154498523870621e-03, +-3.04365200956643270486e-03, +-3.16994843755161225321e-03, +-3.29434006545274672348e-03, +-3.41675727044862646842e-03, +-3.53713160929501439778e-03, +-3.65539585653244531588e-03, +-3.77148404196936751220e-03, +-3.88533148742125408054e-03, +-3.99687484268407104693e-03, +-4.10605212072268164342e-03, +-4.21280273205412725268e-03, +-4.31706751830841783946e-03, +-4.41878878494509144681e-03, +-4.51791033311113327670e-03, +-4.61437749061991125260e-03, +-4.70813714203596311164e-03, +-4.79913775784764073951e-03, +-4.88732942271308690857e-03, +-4.97266386276206447808e-03, +-5.05509447194163030054e-03, +-5.13457633738856073641e-03, +-5.21106626381633106920e-03, +-5.28452279690304685400e-03, +-5.35490624566773484178e-03, +-5.42217870382271597413e-03, +-5.48630407009116985440e-03, +-5.54724806747858376760e-03, +-5.60497826148812720165e-03, +-5.65946407726994771964e-03, +-5.71067681569638677108e-03, +-5.75858966835306532173e-03, +-5.80317773143970965649e-03, +-5.84441801857288768113e-03, +-5.88228947248397703723e-03, +-5.91677297560679570088e-03, +-5.94785135954983314177e-03, +-5.97550941344791256699e-03, +-5.99973389119013312404e-03, +-6.02051351752001286111e-03, +-6.03783899300595460619e-03, +-6.05170299787924879931e-03, +-6.06210019473904081905e-03, +-6.06902723012296262811e-03, +-6.07248273494360914920e-03, +-6.07246732379158708770e-03, +-6.06898359310613279977e-03, +-6.06203611821533403653e-03, +-6.05163144924839458555e-03, +-6.03777810592327594807e-03, +-6.02048657121333555264e-03, +-5.99976928389753336873e-03, +-5.97564062999924889424e-03, +-5.94811693311943397167e-03, +-5.91721644367056848202e-03, +-5.88295932701797356923e-03, +-5.84536765053670151482e-03, +-5.80446536959165673014e-03, +-5.76027831244998057142e-03, +-5.71283416413511518916e-03, +-5.66216244923269020756e-03, +-5.60829451365809760616e-03, +-5.55126350539837404990e-03, +-5.49110435423857436155e-03, +-5.42785375048610279486e-03, +-5.36155012270514343825e-03, +-5.29223361447536504165e-03, +-5.21994606018790722329e-03, +-5.14473095989484690421e-03, +-5.06663345322490039219e-03, +-4.98570029238308044806e-03, +-4.90197981424923389521e-03, +-4.81552191159239240809e-03, +-4.72637800341784222735e-03, +-4.63460100446517250100e-03, +-4.54024529387421233589e-03, +-4.44336668303834617794e-03, +-4.34402238266374564335e-03, +-4.24227096905429278129e-03, +-4.13817234964060018387e-03, +-4.03178772777628563473e-03, +-3.92317956681902026833e-03, +-3.81241155351897623854e-03, +-3.69954856073620007989e-03, +-3.58465660950824235517e-03, +-3.46780283048990500827e-03, +-3.34905542478881141852e-03, +-3.22848362421805775910e-03, +-3.10615765099010905648e-03, +-2.98214867687515662251e-03, +-2.85652878184750828178e-03, +-2.72937091224384606111e-03, +-2.60074883845852087780e-03, +-2.47073711219897686545e-03, +-2.33941102332713016590e-03, +-2.20684655631157985653e-03, +-2.07312034631475673035e-03, +-1.93830963494213536630e-03, +-1.80249222567671618656e-03, +-1.66574643902788789573e-03, +-1.52815106741598333122e-03, +-1.38978532982251450426e-03, +-1.25072882622996486672e-03, +-1.11106149187807385498e-03, +-9.70863551362263440571e-04, +-8.30215472601808523491e-04, +-6.89197920702451245073e-04, +-5.47891711741154406080e-04, +-4.06377766498845327103e-04, +-2.64737064168374847291e-04, +-1.23050596061868546460e-04, + 1.86006806518760801038e-05, + 1.60135889158271910344e-04, + 3.01474279126209918772e-04, + 4.42535272731790253753e-04, + 5.83238510548296702242e-04, + 7.23503897278638991204e-04, + 8.63251647300782411557e-04, + 1.00240233000493386348e-03, + 1.14087691489260295227e-03, + 1.27859681641420436932e-03, + 1.41548393851902284610e-03, + 1.55146071889291931739e-03, + 1.68645017285750319601e-03, + 1.82037593690758878195e-03, + 1.95316231186109341353e-03, + 2.08473430559764265693e-03, + 2.21501767536104888362e-03, + 2.34393896960388269796e-03, + 2.47142556934688362516e-03, + 2.59740572903363739141e-03, + 2.72180861685599774502e-03, + 2.84456435452711767914e-03, + 2.96560405648055866804e-03, + 3.08485986847369889757e-03, + 3.20226500557270433653e-03, + 3.31775378949923562683e-03, + 3.43126168531712261514e-03, + 3.54272533743877921647e-03, + 3.65208260493136678895e-03, + 3.75927259610300519913e-03, + 3.86423570235000643155e-03, + 3.96691363124569706944e-03, + 4.06724943885357868856e-03, + 4.16518756124574941052e-03, + 4.26067384521043503870e-03, + 4.35365557813031326534e-03, + 4.44408151701685457530e-03, + 4.53190191668225664939e-03, + 4.61706855703673899743e-03, + 4.69953476949353052966e-03, + 4.77925546246841040365e-03, + 4.85618714595966241565e-03, + 4.93028795519530847746e-03, + 5.00151767333411288730e-03, + 5.06983775320908342660e-03, + 5.13521133810092809957e-03, + 5.19760328153088136532e-03, + 5.25698016606174298865e-03, + 5.31331032109820002030e-03, + 5.36656383967527069595e-03, + 5.41671259422796692179e-03, + 5.46373025133245135421e-03, + 5.50759228541199737789e-03, + 5.54827599139992924671e-03, + 5.58576049635388805631e-03, + 5.62002677001447251137e-03, + 5.65105763430437738060e-03, + 5.67883777176233280753e-03, + 5.70335373290816339403e-03, + 5.72459394253559995802e-03, + 5.74254870493012391924e-03, + 5.75721020800935671946e-03, + 5.76857252638474007206e-03, + 5.77663162334343931875e-03, + 5.78138535175009606049e-03, + 5.78283345386879782390e-03, + 5.78097756010611391053e-03, + 5.77582118667672138324e-03, + 5.76736973219383122768e-03, + 5.75563047318704626432e-03, + 5.74061255855102051116e-03, + 5.72232700292902695532e-03, + 5.70078667903584773713e-03, + 5.67600630892513106918e-03, + 5.64800245420722570738e-03, + 5.61679350522356971021e-03, + 5.58239966918474238289e-03, + 5.54484295727977402612e-03, + 5.50414717076463597123e-03, + 5.46033788603883952356e-03, + 5.41344243871932310347e-03, + 5.36348990672138540431e-03, + 5.31051109235732010649e-03, + 5.25453850346318130510e-03, + 5.19560633356600486132e-03, + 5.13375044110239622114e-03, + 5.06900832770268514743e-03, + 5.00141911555166893133e-03, + 4.93102352384138312158e-03, + 4.85786384432904984332e-03, + 4.78198391601513880800e-03, + 4.70342909895635295087e-03, + 4.62224624722982427999e-03, + 4.53848368106374473741e-03, + 4.45219115815146792431e-03, + 4.36341984416594753926e-03, + 4.27222228249233334368e-03, + 4.17865236319510044427e-03, + 4.08276529124071765886e-03, + 3.98461755399166870500e-03, + 3.88426688799294646953e-03, + 3.78177224506918985281e-03, + 3.67719375775360296163e-03, + 3.57059270406730406081e-03, + 3.46203147167215485522e-03, + 3.35157352141467277523e-03, + 3.23928335028530935830e-03, + 3.12522645381305575613e-03, + 3.00946928791781488297e-03, + 2.89207923024227455538e-03, + 2.77312454098672077352e-03, + 2.65267432326827179087e-03, + 2.53079848302840103302e-03, + 2.40756768851164678139e-03, + 2.28305332933951632760e-03, + 2.15732747520132111738e-03, + 2.03046283418941569954e-03, + 1.90253271079930631401e-03, + 1.77361096362036439224e-03, + 1.64377196274210417119e-03, + 1.51309054689958370071e-03, + 1.38164198038311938042e-03, + 1.24950190973654160810e-03, + 1.11674632027006139751e-03, + 9.83451492411185164075e-04, + 8.49693957919833188497e-04, + 7.15550455992367039418e-04, + 5.81097889279802068928e-04, + 4.46413279844896004802e-04, + 3.11573725084547952131e-04, + 1.76656353640993331018e-04, + 4.17382813286828151375e-05, +-9.31034328996876200512e-05, +-2.27791830921029737336e-04, +-3.62250099320780654093e-04, +-4.96401613154530668010e-04, +-6.30169979571938514672e-04, +-7.63479081274113916857e-04, +-8.96253119781942569726e-04, +-1.02841665849006422100e-03, +-1.15989466548260746100e-03, +-1.29061255608525294117e-03, +-1.42049623513107697685e-03, +-1.54947213891506270153e-03, +-1.67746727681411891310e-03, +-1.80440927254837480201e-03, +-1.93022640506252275011e-03, +-2.05484764900032337159e-03, +-2.17820271475373814299e-03, +-2.30022208806093461653e-03, +-2.42083706913298482913e-03, +-2.53997981128547666713e-03, +-2.65758335905543320934e-03, +-2.77358168577903838048e-03, +-2.88790973061320895704e-03, +-3.00050343497665914297e-03, +-3.11129977839202497697e-03, +-3.22023681370834334581e-03, +-3.32725370168476981825e-03, +-3.43229074491519740159e-03, +-3.53528942107627329461e-03, +-3.63619241547926243599e-03, +-3.73494365290821112024e-03, +-3.83148832872629279550e-03, +-3.92577293923390257396e-03, +-4.01774531126125340058e-03, +-4.10735463097804467947e-03, +-4.19455147190698693360e-03, +-4.27928782212313139899e-03, +-4.36151711062546069975e-03, +-4.44119423286594081079e-03, +-4.51827557542231091070e-03, +-4.59271903980044363808e-03, +-4.66448406535440850823e-03, +-4.73353165131090974221e-03, +-4.79982437788653917843e-03, +-4.86332642648651045092e-03, +-4.92400359897397343206e-03, +-4.98182333599925253331e-03, +-5.03675473437993799497e-03, +-5.08876856352186244387e-03, +-5.13783728087296304166e-03, +-5.18393504640126713545e-03, +-5.22703773609024553021e-03, +-5.26712295444329344635e-03, +-5.30417004599272740029e-03, +-5.33816010580571553151e-03, +-5.36907598898301533646e-03, +-5.39690231914530423041e-03, +-5.42162549590326486165e-03, +-5.44323370130771460457e-03, +-5.46171690527704530721e-03, +-5.47706686999947442440e-03, +-5.48927715330848470243e-03, +-5.49834311103008545329e-03, +-5.50426189830165689398e-03, +-5.50703246986195688040e-03, +-5.50665557931325801155e-03, +-5.50313377735658394718e-03, +-5.49647140900193838936e-03, +-5.48667460975575324578e-03, +-5.47375130078852495386e-03, +-5.45771118308641025457e-03, +-5.43856573059035668105e-03, +-5.41632818232791902330e-03, +-5.39101353354278986507e-03, +-5.36263852582782342415e-03, +-5.33122163626806137848e-03, +-5.29678306560053737545e-03, +-5.25934472539848259925e-03, +-5.21893022428794508411e-03, +-5.17556485320526133559e-03, +-5.12927556970489868793e-03, +-5.08009098132678089954e-03, +-5.02804132803355476738e-03, +-4.97315846372916019885e-03, +-4.91547583686848584689e-03, +-4.85502847017122741990e-03, +-4.79185293945155309919e-03, +-4.72598735157650148841e-03, +-4.65747132156595338576e-03, +-4.58634594884884446570e-03, +-4.51265379268859113254e-03, +-4.43643884679333078136e-03, +-4.35774651312552125521e-03, +-4.27662357492689104710e-03, +-4.19311816897408994737e-03, +-4.10727975708242813713e-03, +-4.01915909687342119000e-03, +-3.92880821182439374240e-03, +-3.83628036061678823893e-03, +-3.74163000580234744730e-03, +-3.64491278180403876011e-03, +-3.54618546227291209921e-03, +-3.44550592681680360740e-03, +-3.34293312712312645080e-03, +-3.23852705249417973515e-03, +-3.13234869481537631791e-03, +-3.02446001297665325452e-03, +-2.91492389676846486157e-03, +-2.80380413027231812501e-03, +-2.69116535476798942814e-03, +-2.57707303117848647925e-03, +-2.46159340207523572031e-03, +-2.34479345326362147856e-03, +-2.22674087497457245249e-03, +-2.10750402268079263524e-03, +-1.98715187756321907606e-03, +-1.86575400664854376166e-03, +-1.74338052264242380010e-03, +-1.62010204348048895799e-03, +-1.49598965162051219212e-03, +-1.37111485310015116836e-03, +-1.24554953638238521431e-03, +-1.11936593101341890638e-03, +-9.92636566116329244550e-04, +-8.65434228744452519431e-04, +-7.37831922117954900481e-04, +-6.09902823768643741718e-04, +-4.81720243615482051399e-04, +-3.53357581995873909833e-04, +-2.24888287676710109473e-04, +-9.63858158682636068570e-05, + 3.20764137345539367911e-05, + 1.60425058858032064824e-04, + 2.88586896482438703439e-04, + 4.16488864574161247057e-04, + 5.44058103695506324778e-04, + 6.71221998467804803826e-04, + 7.97908218864774886926e-04, + 9.24044761311549125993e-04, + 1.04955998956755358967e-03, + 1.17438267536891884947e-03, + 1.29844203880782817391e-03, + 1.42166778842579637730e-03, + 1.54399016099864027675e-03, + 1.66533996098952152137e-03, + 1.78564859964935114707e-03, + 1.90484813374091114212e-03, + 2.02287130386640369786e-03, + 2.13965157237518523517e-03, + 2.25512316083227538563e-03, + 2.36922108702373405281e-03, + 2.48188120148188241104e-03, + 2.59304022350648980672e-03, + 2.70263577666357253729e-03, + 2.81060642374125237153e-03, + 2.91689170114364185876e-03, + 3.02143215270252868399e-03, + 3.12416936288921476272e-03, + 3.22504598940713581648e-03, + 3.32400579514743541032e-03, + 3.42099367948939334788e-03, + 3.51595570892898222001e-03, + 3.60883914701814589171e-03, + 3.69959248359746136620e-03, + 3.78816546330745101967e-03, + 3.87450911336219023379e-03, + 3.95857577056929390430e-03, + 4.04031910758215120211e-03, + 4.11969415836998739677e-03, + 4.19665734289097897003e-03, + 4.27116649095604910408e-03, + 4.34318086526945621589e-03, + 4.41266118363398390095e-03, + 4.47956964030860743664e-03, + 4.54386992650717726205e-03, + 4.60552725002660520714e-03, + 4.66450835399471325227e-03, + 4.72078153472709621807e-03, + 4.77431665868354501020e-03, + 4.82508517851539756732e-03, + 4.87306014819507884311e-03, + 4.91821623721916140887e-03, + 4.96052974387923596711e-03, + 4.99997860759186524976e-03, + 5.03654242028247437629e-03, + 5.07020243681679735892e-03, + 5.10094158447498870201e-03, + 5.12874447146327485519e-03, + 5.15359739445947657999e-03, + 5.17548834518845573410e-03, + 5.19440701602455999486e-03, + 5.21034480461868027695e-03, + 5.22329481754779667568e-03, + 5.23325187298585500772e-03, + 5.24021250239507709739e-03, + 5.24417495123738995610e-03, + 5.24513917870653937486e-03, + 5.24310685648145778648e-03, + 5.23808136650251530281e-03, + 5.23006779777264278752e-03, + 5.21907294218578940437e-03, + 5.20510528938584581676e-03, + 5.18817502065979652137e-03, + 5.16829400186912500670e-03, + 5.14547577542429773745e-03, + 5.11973555130774103661e-03, + 5.09109019715092269570e-03, + 5.05955822737205133249e-03, + 5.02515979138124391917e-03, + 4.98791666086073268160e-03, + 4.94785221612767823346e-03, + 4.90499143158841868773e-03, + 4.85936086029322127783e-03, + 4.81098861760061516368e-03, + 4.75990436396146916753e-03, + 4.70613928683348472365e-03, + 4.64972608173691136918e-03, + 4.59069893246278216276e-03, + 4.52909349044612261070e-03, + 4.46494685331585636212e-03, + 4.39829754263475290049e-03, + 4.32918548084257250735e-03, + 4.25765196741618740656e-03, + 4.18373965426069652218e-03, + 4.10749252034667798605e-03, + 4.02895584560788132256e-03, + 3.94817618411542111539e-03, + 3.86520133654418484789e-03, + 3.78008032194739225507e-03, + 3.69286334885604366693e-03, + 3.60360178572117573551e-03, + 3.51234813071479813271e-03, + 3.41915598090793311503e-03, + 3.32408000084427699555e-03, + 3.22717589052724015269e-03, + 3.12850035283901645525e-03, + 3.02811106041162708680e-03, + 2.92606662196800764927e-03, + 2.82242654815364601290e-03, + 2.71725121687837328777e-03, + 2.61060183818851918036e-03, + 2.50254041868949728133e-03, + 2.39312972554039504053e-03, + 2.28243325004017514127e-03, + 2.17051517082786447205e-03, + 2.05744031671671037328e-03, + 1.94327412918531700070e-03, + 1.82808262454552442576e-03, + 1.71193235581180232437e-03, + 1.59489037429026681535e-03, + 1.47702419091290675264e-03, + 1.35840173733748205247e-03, + 1.23909132683596356558e-03, + 1.11916161499407847656e-03, + 9.98681560244074617572e-04, + 8.77720384254470167330e-04, + 7.56347532198058721681e-04, + 6.34632632921996054504e-04, + 5.12645459042746680714e-04, + 3.90455886987906247536e-04, + 2.68133857008314943106e-04, + 1.45749333184361831153e-04, + 2.33722634472747536666e-05, +-9.89274603607503039181e-05, +-2.21080042364225074413e-04, +-3.43015822447986784560e-04, +-4.64665315944092405156e-04, +-5.85959253188382740186e-04, +-7.06828618925680403524e-04, +-8.27204691540118683922e-04, +-9.47019082088787164143e-04, +-1.06620377311637771697e-03, +-1.18469115722925682696e-03, +-1.30241407540605423285e-03, +-1.41930585502448507011e-03, +-1.53530034758192469001e-03, +-1.65033196608840252578e-03, +-1.76433572211173142659e-03, +-1.87724726245334949150e-03, +-1.98900290543319513067e-03, +-2.09953967676512883930e-03, +-2.20879534500175757350e-03, +-2.31670845652815794724e-03, +-2.42321837008570468985e-03, +-2.52826529080659367574e-03, +-2.63179030373909264226e-03, +-2.73373540684600496026e-03, +-2.83404354345699518308e-03, +-2.93265863415691175817e-03, +-3.02952560809236284833e-03, +-3.12459043367923185522e-03, +-3.21780014869336387223e-03, +-3.30910288972877109082e-03, +-3.39844792100587331576e-03, +-3.48578566251492739242e-03, +-3.57106771747796791425e-03, +-3.65424689911476559614e-03, +-3.73527725669808635320e-03, +-3.81411410088312429617e-03, +-3.89071402829827646050e-03, +-3.96503494538289445737e-03, +-4.03703609145932267727e-03, +-4.10667806102655782996e-03, +-4.17392282526347826316e-03, +-4.23873375272956244564e-03, +-4.30107562925237472268e-03, +-4.36091467699083017162e-03, +-4.41821857266369143885e-03, +-4.47295646493412607514e-03, +-4.52509899094063333669e-03, +-4.57461829196504320139e-03, +-4.62148802823035640547e-03, +-4.66568339281999474449e-03, +-4.70718112471093987764e-03, +-4.74595952091446966065e-03, +-4.78199844771800587628e-03, +-4.81527935102211632201e-03, +-4.84578526576791637770e-03, +-4.87350082444968323026e-03, +-4.89841226470876054538e-03, +-4.92050743600499964486e-03, +-4.93977580536274565870e-03, +-4.95620846218847079662e-03, +-4.96979812215835037303e-03, +-4.98053913017405553570e-03, +-4.98842746238571579237e-03, +-4.99346072728172954425e-03, +-4.99563816584549461736e-03, +-4.99496065077936236831e-03, +-4.99143068479745467825e-03, +-4.98505239798852691629e-03, +-4.97583154425139829319e-03, +-4.96377549680547796446e-03, +-4.94889324277973576688e-03, +-4.93119537688388714231e-03, +-4.91069409416598247342e-03, +-4.88740318186142198853e-03, +-4.86133801033847897516e-03, +-4.83251552314631609847e-03, +-4.80095422617195580206e-03, +-4.76667417591256168535e-03, +-4.72969696687120574191e-03, +-4.69004571808321647775e-03, +-4.64774505878175377138e-03, +-4.60282111321146884114e-03, +-4.55530148459956044787e-03, +-4.50521523829377698589e-03, +-4.45259288407801132742e-03, +-4.39746635767579701487e-03, +-4.33986900145311854660e-03, +-4.27983554433203870759e-03, +-4.21740208092733371431e-03, +-4.15260604991831393240e-03, +-4.08548621166932371396e-03, +-4.01608262511158123353e-03, +-3.94443662390054836098e-03, +-3.87059079186303405321e-03, +-3.79458893774812806160e-03, +-3.71647606929711776455e-03, +-3.63629836664845860345e-03, +-3.55410315509214558630e-03, +-3.46993887719018040405e-03, +-3.38385506427993278805e-03, +-3.29590230737648436782e-03, +-3.20613222749113312843e-03, +-3.11459744538398987032e-03, +-3.02135155076756461295e-03, +-2.92644907097984593655e-03, +-2.82994543914506487339e-03, +-2.73189696184072483912e-03, +-2.63236078628936763860e-03, +-2.53139486709509815843e-03, +-2.42905793254300297890e-03, +-2.32540945048183896743e-03, +-2.22050959380982104382e-03, +-2.11441920558280097714e-03, +-2.00719976376547218355e-03, +-1.89891334564696082597e-03, +-1.78962259193952521845e-03, +-1.67939067058208314070e-03, +-1.56828124026987358701e-03, +-1.45635841373061535042e-03, +-1.34368672076823521266e-03, +-1.23033107109642224179e-03, +-1.11635671698205856534e-03, +-1.00182921572098456581e-03, +-8.86814391967279472273e-04, +-7.71378299937657582568e-04, +-6.55587185513229354222e-04, +-5.39507448258485936346e-04, +-4.23205603382631467824e-04, +-3.06748243661661022710e-04, +-1.90202001344411987527e-04, +-7.36335100648440309687e-05, + 4.28906332185422347128e-05, + 1.59303906234412831922e-04, + 2.75539899338800254799e-04, + 3.91532353363562794085e-04, + 5.07215197350502681149e-04, + 6.22522586150107753653e-04, + 7.37388937863388033329e-04, + 8.51748971105957086540e-04, + 9.65537742072175879035e-04, + 1.07869068137969592591e-03, + 1.19114363067259008272e-03, + 1.30283287896230275983e-03, + 1.41369519868671613717e-03, + 1.52366788146634829677e-03, + 1.63268877353659261353e-03, + 1.74069631083787878384e-03, + 1.84762955374296743323e-03, + 1.95342822140135439005e-03, + 2.05803272568219793037e-03, + 2.16138420469669332441e-03, + 2.26342455588016133738e-03, + 2.36409646861654226466e-03, + 2.46334345638605676718e-03, + 2.56110988841841760721e-03, + 2.65734102083372766834e-03, + 2.75198302725402016780e-03, + 2.84498302886748277024e-03, + 2.93628912392977997961e-03, + 3.02585041668512657459e-03, + 3.11361704569121855099e-03, + 3.19954021153272608058e-03, + 3.28357220390771429100e-03, + 3.36566642807112174907e-03, + 3.44577743062223634807e-03, + 3.52386092462112724549e-03, + 3.59987381401977125581e-03, + 3.67377421739513865956e-03, + 3.74552149097084462886e-03, + 3.81507625091497340475e-03, + 3.88240039490136924424e-03, + 3.94745712292331966259e-03, + 4.01021095734782184045e-03, + 4.07062776219968818631e-03, + 4.12867476166478130500e-03, + 4.18432055780340594886e-03, + 4.23753514746243783312e-03, + 4.28828993837902447406e-03, + 4.33655776446637518384e-03, + 4.38231290027339768361e-03, + 4.42553107461083304608e-03, + 4.46618948333678180557e-03, + 4.50426680129448111373e-03, + 4.53974319339683820423e-03, + 4.57260032485135199665e-03, + 4.60282137052065234983e-03, + 4.63039102341378759620e-03, + 4.65529550230404237654e-03, + 4.67752255846963938685e-03, + 4.69706148155405248112e-03, + 4.71390310454339756668e-03, + 4.72803980785840502477e-03, + 4.73946552255972292089e-03, + 4.74817573266493424267e-03, + 4.75416747657694122031e-03, + 4.75743934762336718319e-03, + 4.75799149370748075683e-03, + 4.75582561607138833149e-03, + 4.75094496717288084647e-03, + 4.74335434767782487125e-03, + 4.73306010257048929979e-03, + 4.72007011638460489966e-03, + 4.70439380755864264283e-03, + 4.68604212191906475959e-03, + 4.66502752529606660309e-03, + 4.64136399527643843388e-03, + 4.61506701209918757806e-03, + 4.58615354869955273859e-03, + 4.55464205990770056726e-03, + 4.52055247080917176061e-03, + 4.48390616427393924603e-03, + 4.44472596766223859710e-03, + 4.40303613871486330955e-03, + 4.35886235063746938639e-03, + 4.31223167638676834618e-03, + 4.26317257216925812185e-03, + 4.21171486016196257307e-03, + 4.15788971046581433411e-03, + 4.10172962230226281072e-03, + 4.04326840446501793724e-03, + 3.98254115503794432068e-03, + 3.91958424039167124125e-03, + 3.85443527347131180763e-03, + 3.78713309138849164512e-03, + 3.71771773232995421388e-03, + 3.64623041179842725945e-03, + 3.57271349819778243767e-03, + 3.49721048777782827360e-03, + 3.41976597895377260397e-03, + 3.34042564601502072266e-03, + 3.25923621223874176306e-03, + 3.17624542242462160752e-03, + 3.09150201486607309476e-03, + 3.00505569277494284652e-03, + 2.91695709517621800527e-03, + 2.82725776728985633834e-03, + 2.73601013041636529841e-03, + 2.64326745134584257038e-03, + 2.54908381130463648420e-03, + 2.45351407446147209979e-03, + 2.35661385600897553202e-03, + 2.25843948984021103410e-03, + 2.15904799583798876969e-03, + 2.05849704679780722699e-03, + 1.95684493500119767798e-03, + 1.85415053846056882350e-03, + 1.75047328685429747983e-03, + 1.64587312717267382142e-03, + 1.54041048909200266152e-03, + 1.43414625010112694974e-03, + 1.32714170039615556723e-03, + 1.21945850756623999298e-03, + 1.11115868108982397341e-03, + 1.00230453666194673813e-03, + 8.92958660373076220512e-04, + 7.83183872760047513316e-04, + 6.73043192749742938061e-04, + 5.62599801516196619360e-04, + 4.51917006271797402298e-04, + 3.41058204013367112766e-04, + 2.30086845243956402514e-04, + 1.19066397690317975016e-04, + 8.06031003876342309552e-06, +-1.02868024292534745090e-04, +-2.13655303322282262481e-04, +-3.24238352595229727994e-04, +-4.34554161172920089696e-04, +-5.44539917503692838356e-04, +-6.54133045151543304589e-04, +-7.63271238365370997651e-04, +-8.71892497466585482749e-04, +-9.79935164035776202357e-04, +-1.08733795587835245164e-03, +-1.19404000174937055881e-03, +-1.29998087581786859156e-03, +-1.40510063185121983863e-03, +-1.50933983710020702684e-03, +-1.61263960586564250761e-03, +-1.71494163272752683097e-03, +-1.81618822541869504202e-03, +-1.91632233732264294253e-03, +-2.01528759957979742429e-03, +-2.11302835278164621163e-03, +-2.20948967823741222391e-03, +-2.30461742879315041599e-03, +-2.39835825918845125734e-03, +-2.49065965593134232975e-03, +-2.58146996667703255632e-03, +-2.67073842909245186619e-03, +-2.75841519919107873438e-03, +-2.84445137912224619431e-03, +-2.92879904439931598031e-03, +-3.01141127055178960126e-03, +-3.09224215918633147174e-03, +-3.17124686344243166339e-03, +-3.24838161282851346778e-03, +-3.32360373742473678635e-03, +-3.39687169143964044424e-03, +-3.46814507610627249454e-03, +-3.53738466190720588292e-03, +-3.60455241011424683262e-03, +-3.66961149363298272039e-03, +-3.73252631713888970155e-03, +-3.79326253649527652539e-03, +-3.85178707744242114497e-03, +-3.90806815354677143659e-03, +-3.96207528340193453065e-03, +-4.01377930707108587782e-03, +-4.06315240176249869997e-03, +-4.11016809672954883115e-03, +-4.15480128738748670514e-03, +-4.19702824863931681781e-03, +-4.23682664740382061708e-03, +-4.27417555433919245378e-03, +-4.30905545475612165168e-03, +-4.34144825871471493756e-03, +-4.37133731030028924863e-03, +-4.39870739607276222544e-03, +-4.42354475268612757494e-03, +-4.44583707367407054284e-03, +-4.46557351539804588125e-03, +-4.48274470215558658998e-03, +-4.49734273044633849070e-03, +-4.50936117239380054866e-03, +-4.51879507832192439665e-03, +-4.52564097848520176248e-03, +-4.52989688395227449447e-03, +-4.53156228664297524439e-03, +-4.53063815851947795238e-03, +-4.52712694993263019272e-03, +-4.52103258712507720396e-03, +-4.51236046889318294373e-03, +-4.50111746241027566029e-03, +-4.48731189821427022685e-03, +-4.47095356436308811326e-03, +-4.45205369976202098431e-03, +-4.43062498666702171690e-03, +-4.40668154236938374585e-03, +-4.38023891006674489373e-03, +-4.35131404892644905319e-03, +-4.31992532334727567106e-03, +-4.28609249142686190431e-03, +-4.24983669264115699465e-03, +-4.21118043474420344213e-03, +-4.17014757989600526322e-03, +-4.12676333002717343063e-03, +-4.08105421144885384399e-03, +-4.03304805871769478376e-03, +-3.98277399776586060048e-03, +-3.93026242830538889012e-03, +-3.87554500551830520202e-03, +-3.81865462104316469652e-03, +-3.75962538326934676142e-03, +-3.69849259695105700083e-03, +-3.63529274215302917322e-03, +-3.57006345254048127261e-03, +-3.50284349302629844855e-03, +-3.43367273678861842368e-03, +-3.36259214167245173294e-03, +-3.28964372598887933724e-03, +-3.21487054372729570695e-03, +-3.13831665919360848840e-03, +-3.06002712109050643147e-03, +-2.98004793605501560813e-03, +-2.89842604166773779029e-03, +-2.81520927895077040931e-03, +-2.73044636437046704669e-03, +-2.64418686136011710577e-03, +-2.55648115138037068314e-03, +-2.46738040453385034864e-03, +-2.37693654975105290658e-03, +-2.28520224456495602700e-03, +-2.19223084449187820971e-03, +-2.09807637203635911904e-03, +-2.00279348533807409136e-03, +-1.90643744647894558715e-03, +-1.80906408946890644336e-03, +-1.71072978792818604712e-03, +-1.61149142248648530144e-03, +-1.51140634791550681169e-03, +-1.41053236001619538946e-03, +-1.30892766227735197690e-03, +-1.20665083232744858345e-03, +-1.10376078819640946992e-03, +-1.00031675440937460608e-03, +-8.96378227929317322395e-04, +-7.92004943969952133684e-04, +-6.87256841697829728294e-04, +-5.82194029843374478810e-04, +-4.76876752240620047432e-04, +-3.71365353315354857280e-04, +-2.65720243541443139953e-04, +-1.60001864885065504330e-04, +-5.42706562566359684624e-05, + 5.14129810098762333082e-05, + 1.56988717630401143676e-04, + 2.62396330778088919793e-04, + 3.67575738403138686013e-04, + 4.72467033447351674163e-04, + 5.77010517933939639720e-04, + 6.81146736911458490320e-04, + 7.84816512234211456633e-04, + 8.87960976159937634238e-04, + 9.90521604744005372892e-04, + 1.09244025101365264951e-03, + 1.19365917790164059384e-03, + 1.29412109092141174894e-03, + 1.39376917056518003293e-03, + 1.49254710440663968495e-03, + 1.59039911889015199951e-03, + 1.68727001078853872801e-03, + 1.78310517831170383361e-03, + 1.87785065184860474295e-03, + 1.97145312432514584547e-03, + 2.06385998116165444646e-03, + 2.15501932981150296637e-03, + 2.24488002886593339402e-03, + 2.33339171670872728634e-03, + 2.42050483970316981583e-03, + 2.50617067989698880798e-03, + 2.59034138222976727944e-03, + 2.67296998122616528970e-03, + 2.75401042716228762475e-03, + 2.83341761168887876915e-03, + 2.91114739289797088209e-03, + 2.98715661981875787653e-03, + 3.06140315632929442893e-03, + 3.13384590447068249811e-03, + 3.20444482715097822209e-03, + 3.27316097022614747175e-03, + 3.33995648394608485657e-03, + 3.40479464375383631194e-03, + 3.46763987042658736876e-03, + 3.52845774954753865424e-03, + 3.58721505029781922991e-03, + 3.64387974355847871905e-03, + 3.69842101931248078139e-03, + 3.75080930333746573671e-03, + 3.80101627318009003750e-03, + 3.84901487340377030863e-03, + 3.89477933010077409515e-03, + 3.93828516466203197577e-03, + 3.97950920679663710383e-03, + 4.01842960679405468427e-03, + 4.05502584702343085721e-03, + 4.08927875266308724772e-03, + 4.12117050165479448243e-03, + 4.15068463387839852591e-03, + 4.17780605954134933583e-03, + 4.20252106677934406803e-03, + 4.22481732846414353988e-03, + 4.24468390821542990859e-03, + 4.26211126561366546173e-03, + 4.27709126061177457440e-03, + 4.28961715714353680751e-03, + 4.29968362592737362443e-03, + 4.30728674646440722745e-03, + 4.31242400823038558866e-03, + 4.31509431106120045635e-03, + 4.31529796473259855127e-03, + 4.31303668773473300457e-03, + 4.30831360524300700093e-03, + 4.30113324628681858303e-03, + 4.29150154011852507513e-03, + 4.27942581178534283554e-03, + 4.26491477690706718290e-03, + 4.24797853566351822641e-03, + 4.22862856599543705111e-03, + 4.20687771602348218464e-03, + 4.18274019569020352044e-03, + 4.15623156763024730748e-03, + 4.12736873727475445106e-03, + 4.09616994219598982985e-03, + 4.06265474069904698046e-03, + 4.02684399966749852207e-03, + 3.98875988167053836808e-03, + 3.94842583133988254962e-03, + 3.90586656102404668894e-03, + 3.86110803572960138361e-03, + 3.81417745735749278216e-03, + 3.76510324824506480840e-03, + 3.71391503402302824294e-03, + 3.66064362579748142634e-03, + 3.60532100166869413568e-03, + 3.54798028759637515753e-03, + 3.48865573762383116702e-03, + 3.42738271347229261563e-03, + 3.36419766351780209421e-03, + 3.29913810116290494648e-03, + 3.23224258261611266038e-03, + 3.16355068409222362283e-03, + 3.09310297844691411973e-03, + 3.02094101125942446004e-03, + 2.94710727637745740354e-03, + 2.87164519093818793039e-03, + 2.79459906988119548971e-03, + 2.71601409996710457459e-03, + 2.63593631331708773413e-03, + 2.55441256048993380751e-03, + 2.47149048311133935976e-03, + 2.38721848607121494082e-03, + 2.30164570930673547527e-03, + 2.21482199918544885378e-03, + 2.12679787950668637911e-03, + 2.03762452213744876123e-03, + 1.94735371729998175613e-03, + 1.85603784352819439415e-03, + 1.76372983731039952200e-03, + 1.67048316243592642229e-03, + 1.57635177906330727939e-03, + 1.48139011252795978722e-03, + 1.38565302190747641209e-03, + 1.28919576836194387306e-03, + 1.19207398326919835826e-03, + 1.09434363617172251450e-03, + 9.96061002553666387932e-04, + 8.97282631468103723978e-04, + 7.98065313031665838489e-04, + 6.98466045805186700954e-04, + 5.98542004080726075879e-04, + 4.98350505091392156909e-04, + 3.97948976164492736543e-04, + 2.97394921836138706028e-04, + 1.96745890946085639616e-04, + 9.60594437324946328737e-05, +-4.60688105713253110850e-06, +-1.05195599015863548308e-04, +-2.05649312873547269803e-04, +-3.05910745218120614427e-04, +-4.05922771124209050102e-04, +-5.05628450670332911694e-04, +-6.04971061326233742333e-04, +-7.03894130191895397823e-04, +-8.02341466069983314836e-04, +-9.00257191353478103575e-04, +-9.97585773710441469850e-04, +-1.09427205754784526159e-03, +-1.19026129523734734011e-03, +-1.28549917808361388767e-03, +-1.37993186702002005456e-03, +-1.47350602301274868564e-03, +-1.56616883715618676436e-03, +-1.65786806044407471726e-03, +-1.74855203319811505248e-03, +-1.83816971413744510017e-03, +-1.92667070907424605244e-03, +-2.01400529921775661019e-03, +-2.10012446907152346490e-03, +-2.18497993390813667614e-03, +-2.26852416680606251351e-03, +-2.35071042523344675770e-03, +-2.43149277716405484012e-03, +-2.51082612671079579217e-03, +-2.58866623926247820323e-03, +-2.66496976610981501504e-03, +-2.73969426854743253880e-03, +-2.81279824143723829188e-03, +-2.88424113622183812475e-03, +-2.95398338337400341927e-03, +-3.02198641426984970434e-03, +-3.08821268247472897547e-03, +-3.15262568442887820136e-03, +-3.21518997952162247436e-03, +-3.27587120954407487808e-03, +-3.33463611750868180184e-03, +-3.39145256582575700330e-03, +-3.44628955382705274429e-03, +-3.49911723462676847382e-03, +-3.54990693131099601179e-03, +-3.59863115244673462817e-03, +-3.64526360690210944615e-03, +-3.68977921797001727142e-03, +-3.73215413678737884667e-03, +-3.77236575504307771953e-03, +-3.81039271696794737063e-03, +-3.84621493059991411204e-03, +-3.87981357831906903399e-03, +-3.91117112664715865095e-03, +-3.94027133530578613924e-03, +-3.96709926552936235911e-03, +-3.99164128762850064364e-03, +-4.01388508779965472173e-03, +-4.03381967417829664230e-03, +-4.05143538213234219447e-03, +-4.06672387879341342559e-03, +-4.07967816682406215351e-03, +-4.09029258741918071846e-03, +-4.09856282254066582593e-03, +-4.10448589638437531107e-03, +-4.10806017607942119269e-03, +-4.10928537161966977997e-03, +-4.10816253502826328470e-03, +-4.10469405875612397550e-03, +-4.09888367331595702275e-03, +-4.09073644415366196453e-03, +-4.08025876775947385355e-03, +-4.06745836702175275756e-03, +-4.05234428582641227623e-03, +-4.03492688290585550803e-03, +-4.01521782494141353526e-03, +-3.99323007892370650251e-03, +-3.96897790377597620148e-03, +-3.94247684124562208785e-03, +-3.91374370606971909436e-03, +-3.88279657542071584067e-03, +-3.84965477763883840226e-03, +-3.81433888025815110920e-03, +-3.77687067733369942479e-03, +-3.73727317607745312261e-03, +-3.69557058281119732435e-03, +-3.65178828824497432592e-03, +-3.60595285208962579651e-03, +-3.55809198701380119054e-03, +-3.50823454195329457322e-03, +-3.45641048478445914172e-03, +-3.40265088437114587849e-03, +-3.34698789199610203388e-03, +-3.28945472218769140865e-03, +-3.23008563295407733276e-03, +-3.16891590543550479703e-03, +-3.10598182298758417746e-03, +-3.04132064970752489380e-03, +-2.97497060841662606598e-03, +-2.90697085811037359698e-03, +-2.83736147089205630045e-03, +-2.76618340840093044491e-03, +-2.69347849775016792359e-03, +-2.61928940698839384654e-03, +-2.54365962009905433386e-03, +-2.46663341155241517058e-03, +-2.38825582042492129409e-03, +-2.30857262410112847040e-03, +-2.22763031157348617012e-03, +-2.14547605635553037887e-03, +-2.06215768902437597554e-03, +-1.97772366940784189923e-03, +-1.89222305843385276043e-03, +-1.80570548965651076455e-03, +-1.71822114047665615993e-03, +-1.62982070307368252966e-03, +-1.54055535506404249653e-03, +-1.45047672990482020075e-03, +-1.35963688705958486193e-03, +-1.26808828194214899543e-03, +-1.17588373565714085327e-03, +-1.08307640455412444898e-03, +-9.89719749612947034476e-04, +-8.95867505677916593256e-04, +-8.01573650558492470548e-04, +-7.06892374014246962534e-04, +-6.11878046641902415860e-04, +-5.16585188682274517973e-04, +-4.21068438765152331434e-04, +-3.25382522609281570492e-04, +-2.29582221697126570396e-04, +-1.33722341940000448565e-04, +-3.78576823531001234436e-05, + 5.79569962416860487149e-05, + 1.53667002468926312949e-04, + 2.49217745588539837595e-04, + 3.44554766605055051796e-04, + 4.39623769277135254159e-04, + 5.34370651012117960608e-04, + 6.28741533626295430459e-04, + 7.22682793954151111819e-04, + 8.16141094289066942359e-04, + 9.09063412638226858026e-04, + 1.00139707277458692852e-03, + 1.09308977406887886975e-03, + 1.18408962108478813154e-03, + 1.27434515292056300961e-03, + 1.36380537228036891051e-03, + 1.45241977425964634632e-03, + 1.54013837482673316033e-03, + 1.62691173898619058195e-03, + 1.71269100860800766242e-03, + 1.79742792990551444876e-03, + 1.88107488054797562099e-03, + 1.96358489639263892462e-03, + 2.04491169781978020942e-03, + 2.12500971565807118477e-03, + 2.20383411668426208024e-03, + 2.28134082868343369618e-03, + 2.35748656505591286728e-03, + 2.43222884895690980023e-03, + 2.50552603695564177905e-03, + 2.57733734220062273013e-03, + 2.64762285707839271562e-03, + 2.71634357535300218975e-03, + 2.78346141377399823244e-03, + 2.84893923314137337971e-03, + 2.91274085881481313576e-03, + 2.97483110065697737429e-03, + 3.03517577239990551941e-03, + 3.09374171042274635074e-03, + 3.15049679193164094970e-03, + 3.20540995253164491541e-03, + 3.25845120318029885659e-03, + 3.30959164651485658951e-03, + 3.35880349254337635945e-03, + 3.40606007369155918199e-03, + 3.45133585919722533919e-03, + 3.49460646884427843240e-03, + 3.53584868602997270254e-03, + 3.57504047015665300802e-03, + 3.61216096834317094977e-03, + 3.64719052644881403663e-03, + 3.68011069940423060295e-03, + 3.71090426084389433947e-03, + 3.73955521203543422501e-03, + 3.76604879010044787946e-03, + 3.79037147552388660465e-03, + 3.81251099894702218107e-03, + 3.83245634724140764663e-03, + 3.85019776886061934965e-03, + 3.86572677846735036217e-03, + 3.87903616083361702654e-03, + 3.89011997401263057497e-03, + 3.89897355178084716390e-03, + 3.90559350534943564709e-03, + 3.90997772434472940645e-03, + 3.91212537705771124658e-03, + 3.91203690996272997887e-03, + 3.90971404650655458141e-03, + 3.90515978516874822171e-03, + 3.89837839679519444422e-03, + 3.88937542120674139765e-03, + 3.87815766308545256322e-03, + 3.86473318714143513133e-03, + 3.84911131256343097898e-03, + 3.83130260675695194506e-03, + 3.81131887837403860592e-03, + 3.78917316963920574116e-03, + 3.76487974797630508064e-03, + 3.73845409694197614373e-03, + 3.70991290647096740377e-03, + 3.67927406243961268098e-03, + 3.64655663555414144908e-03, + 3.61178086957013007655e-03, + 3.57496816885076278136e-03, + 3.53614108527169294233e-03, + 3.49532330447974940585e-03, + 3.45253963151448796734e-03, + 3.40781597580096327210e-03, + 3.36117933552288828195e-03, + 3.31265778138546554757e-03, + 3.26228043977774525078e-03, + 3.21007747534444651261e-03, + 3.15608007297777824404e-03, + 3.10032041923983094425e-03, + 3.04283168322677004605e-03, + 2.98364799688597944274e-03, + 2.92280443479772233245e-03, + 2.86033699343400974954e-03, + 2.79628256990564587336e-03, + 2.73067894021140553096e-03, + 2.66356473700054630430e-03, + 2.59497942686348799513e-03, + 2.52496328716229770719e-03, + 2.45355738241618799925e-03, + 2.38080354025428783324e-03, + 2.30674432695083695896e-03, + 2.23142302255665983882e-03, + 2.15488359564151290768e-03, + 2.07717067766201215345e-03, + 1.99832953697007134966e-03, + 1.91840605247694541945e-03, + 1.83744668698823622119e-03, + 1.75549846022528331473e-03, + 1.67260892154870227308e-03, + 1.58882612239931203697e-03, + 1.50419858847373826526e-03, + 1.41877529164945908116e-03, + 1.33260562167547579916e-03, + 1.24573935764636829771e-03, + 1.15822663927488351057e-03, + 1.07011793797963318704e-03, + 9.81464027805968499546e-04, + 8.92315956194724064533e-04, + 8.02725014617197869804e-04, + 7.12742709092594579033e-04, + 6.22420730605006554577e-04, + 5.31810925436872606979e-04, + 4.40965265435949780974e-04, + 3.49935818232817224746e-04, + 2.58774717425973744146e-04, + 1.67534132751585059917e-04, + 7.62662402549235993827e-05, +-1.49768075193361299620e-05, +-1.06142911301720894524e-04, +-1.97180054818197052647e-04, +-2.88036334442900109586e-04, +-3.78659988762671830508e-04, +-4.68999428038859239934e-04, +-5.59003263548750505343e-04, +-6.48620336790735633678e-04, +-7.37799748534993023869e-04, +-8.26490887705368343190e-04, +-9.14643460074474100654e-04, +-1.00220751675647416767e-03, +-1.08913348248064457101e-03, +-1.17537218363183721542e-03, +-1.26087487603843595614e-03, +-1.34559327249569936173e-03, +-1.42947957000680455318e-03, +-1.51248647672699333688e-03, +-1.59456723859538701364e-03, +-1.67567566564024317960e-03, +-1.75576615794077609337e-03, +-1.83479373123439024051e-03, +-1.91271404215155051663e-03, +-1.98948341306622901448e-03, +-2.06505885654718109729e-03, +-2.13939809939708890443e-03, +-2.21245960626475536570e-03, +-2.28420260281900038002e-03, +-2.35458709846996828985e-03, +-2.42357390862588594968e-03, +-2.49112467647214820554e-03, +-2.55720189426249895279e-03, +-2.62176892410749236631e-03, +-2.68479001825172808662e-03, +-2.74623033882684950205e-03, +-2.80605597707006462066e-03, +-2.86423397199746590513e-03, +-2.92073232852189295164e-03, +-2.97552003500548174764e-03, +-3.02856708023718085299e-03, +-3.07984446982606822549e-03, +-3.12932424200147371596e-03, +-3.17697948281127698356e-03, +-3.22278434071057110627e-03, +-3.26671404053182311278e-03, +-3.30874489683027862494e-03, +-3.34885432659656149396e-03, +-3.38702086132979581640e-03, +-3.42322415846545938939e-03, +-3.45744501215092866347e-03, +-3.48966536336403100604e-03, +-3.51986830936835840347e-03, +-3.54803811250142776476e-03, +-3.57416020829039995585e-03, +-3.59822121289160232194e-03, +-3.62020892984994159536e-03, +-3.64011235617500532313e-03, +-3.65792168773078438943e-03, +-3.67362832393644143589e-03, +-3.68722487177608991560e-03, +-3.69870514911562918089e-03, +-3.70806418732541956396e-03, +-3.71529823320771324796e-03, +-3.72040475022829665933e-03, +-3.72338241905218391911e-03, +-3.72423113738358209715e-03, +-3.72295201911065475747e-03, +-3.71954739275624172296e-03, +-3.71402079923576107501e-03, +-3.70637698892428832029e-03, +-3.69662191803482587105e-03, +-3.68476274431051497790e-03, +-3.67080782203360296914e-03, +-3.65476669635465692756e-03, +-3.63665009694570488807e-03, +-3.61646993098150822468e-03, +-3.59423927545334974051e-03, +-3.56997236882036642416e-03, +-3.54368460200365923210e-03, +-3.51539250872874575737e-03, +-3.48511375522234101432e-03, +-3.45286712927017321387e-03, +-3.41867252864195810338e-03, +-3.38255094889135894329e-03, +-3.34452447053745815023e-03, +-3.30461624563659203332e-03, +-3.26285048375162325951e-03, +-3.21925243732817121037e-03, +-3.17384838648557959795e-03, +-3.12666562323245288482e-03, +-3.07773243511595077232e-03, +-3.02707808831462633209e-03, +-2.97473281018491211153e-03, +-2.92072777127162135427e-03, +-2.86509506679312160940e-03, +-2.80786769761221183597e-03, +-2.74907955070388763247e-03, +-2.68876537913161550372e-03, +-2.62696078154390838186e-03, +-2.56370218120280770127e-03, +-2.49902680455817757105e-03, +-2.43297265937776879124e-03, +-2.36557851244843493979e-03, +-2.29688386686014139187e-03, +-2.22692893888647245465e-03, +-2.15575463447475546355e-03, +-2.08340252536062418495e-03, +-2.00991482481939400667e-03, +-1.93533436306957584878e-03, +-1.85970456234225522789e-03, +-1.78306941163151812420e-03, +-1.70547344113878836074e-03, +-1.62696169642893568967e-03, +-1.54757971231007083503e-03, +-1.46737348645403320284e-03, +-1.38638945277216006635e-03, +-1.30467445456199375615e-03, +-1.22227571743970366350e-03, +-1.13924082207588254177e-03, +-1.05561767674710021286e-03, +-9.71454489722374482305e-04, +-8.86799741498446592036e-04, +-8.01702156900612784851e-04, +-7.16210677064451489704e-04, +-6.30374431316047391209e-04, +-5.44242708964845500752e-04, +-4.57864931026830763918e-04, +-3.71290621893513930751e-04, +-2.84569380963795102567e-04, +-1.97750854252763154373e-04, +-1.10884705997269506742e-04, +-2.40205902709113495357e-05, + 6.27918773732192452876e-05, + 1.49503148216553689897e-04, + 2.36063768629587555480e-04, + 3.22424408250847381943e-04, + 4.08535888074242200738e-04, + 4.94349208428819172911e-04, + 5.79815576835024100270e-04, + 6.64886435721643610786e-04, + 7.49513489987693693958e-04, + 8.33648734393532949913e-04, + 9.17244480766279870337e-04, + 1.00025338500262374157e-03, + 1.08262847385585773974e-03, + 1.16432317148991437694e-03, + 1.24529132578744816673e-03, + 1.32548723439501444157e-03, + 1.40486567049264701387e-03, + 1.48338190827135567480e-03, + 1.56099174810615912330e-03, + 1.63765154140913405528e-03, + 1.71331821514903869137e-03, + 1.78794929602366808354e-03, + 1.86150293427143464359e-03, + 1.93393792710878204520e-03, + 2.00521374178037978947e-03, + 2.07529053820916823889e-03, + 2.14412919123365373897e-03, + 2.21169131241997444365e-03, + 2.27793927143706215546e-03, + 2.34283621698181060769e-03, + 2.40634609724435857836e-03, + 2.46843367990040021484e-03, + 2.52906457162119062410e-03, + 2.58820523708867778964e-03, + 2.64582301750689681194e-03, + 2.70188614859793313494e-03, + 2.75636377807397716516e-03, + 2.80922598257490408261e-03, + 2.86044378406247841104e-03, + 2.90998916566214413729e-03, + 2.95783508694383865181e-03, + 3.00395549863343705108e-03, + 3.04832535674689130908e-03, + 3.09092063613944411163e-03, + 3.13171834346257340134e-03, + 3.17069652952171746399e-03, + 3.20783430102820335192e-03, + 3.24311183173923859094e-03, + 3.27651037297958976080e-03, + 3.30801226353996018562e-03, + 3.33760093894684218077e-03, + 3.36526094009848182609e-03, + 3.39097792126302451446e-03, + 3.41473865743472130771e-03, + 3.43653105104400240569e-03, + 3.45634413801872283564e-03, + 3.47416809319318680913e-03, + 3.48999423506242021850e-03, + 3.50381502987956103268e-03, + 3.51562409509444421737e-03, + 3.52541620213190926708e-03, + 3.53318727850884806152e-03, + 3.53893440928911917967e-03, + 3.54265583787610402466e-03, + 3.54435096614294726028e-03, + 3.54402035390087273917e-03, + 3.54166571770637159458e-03, + 3.53728992900847680203e-03, + 3.53089701163765857378e-03, + 3.52249213863829475218e-03, + 3.51208162844697177607e-03, + 3.49967294041929766896e-03, + 3.48527466970839335317e-03, + 3.46889654149831836577e-03, + 3.45054940459623565863e-03, + 3.43024522438756772347e-03, + 3.40799707515864217997e-03, + 3.38381913179134578146e-03, + 3.35772666083566971931e-03, + 3.32973601096507977951e-03, + 3.29986460282096893265e-03, + 3.26813091825231636506e-03, + 3.23455448895733962272e-03, + 3.19915588453362383092e-03, + 3.16195669994496055336e-03, + 3.12297954241108925363e-03, + 3.08224801772958309845e-03, + 3.03978671603739392451e-03, + 2.99562119702084100892e-03, + 2.94977797458266955549e-03, + 2.90228450097598702356e-03, + 2.85316915041365507313e-03, + 2.80246120216355544194e-03, + 2.75019082313949451285e-03, + 2.69638904999837305393e-03, + 2.64108777075355415781e-03, + 2.58431970591592842859e-03, + 2.52611838917400372689e-03, + 2.46651814762340482884e-03, + 2.40555408155839313758e-03, + 2.34326204383680314694e-03, + 2.27967861883065755005e-03, + 2.21484110097475844769e-03, + 2.14878747292579150296e-03, + 2.08155638334478173060e-03, + 2.01318712431581723840e-03, + 1.94371960841423544429e-03, + 1.87319434543773495790e-03, + 1.80165241881343461162e-03, + 1.72913546169589605814e-03, + 1.65568563276817190023e-03, + 1.58134559176179804313e-03, + 1.50615847470803379538e-03, + 1.43016786893666826216e-03, + 1.35341778783496088576e-03, + 1.27595264538327276757e-03, + 1.19781723048013573688e-03, + 1.11905668107298707052e-03, + 1.03971645810893640986e-03, + 9.59842319320685158357e-04, + 8.79480292862680045757e-04, + 7.98676650812700722817e-04, + 7.17477882554103476610e-04, + 6.35930668054020351715e-04, + 5.54081851052870642121e-04, + 4.71978412180657619888e-04, + 3.89667442014872736876e-04, + 3.07196114096923401319e-04, + 2.24611657920471623987e-04, + 1.41961331909191799819e-04, + 5.92923963973368171269e-05, +-2.33479133692958273222e-05, +-1.05912414198647058736e-04, +-1.88354001866488713528e-04, +-2.70625677966048025676e-04, +-3.52680576676401690700e-04, +-4.34471991434995103831e-04, +-5.15953401499023248805e-04, +-5.97078498380584432939e-04, +-6.77801212140594598610e-04, +-7.58075737526550121580e-04, +-8.37856559939326346609e-04, +-9.17098481214296688997e-04, +-9.95756645202195691743e-04, +-1.07378656313515804741e-03, +-1.15114413876416595180e-03, +-1.22778569325242541826e-03, +-1.30366798981191894975e-03, +-1.37874825806924973352e-03, +-1.45298421814578576985e-03, +-1.52633410443975465511e-03, +-1.59875668909689456869e-03, +-1.67021130515527735372e-03, +-1.74065786935308415041e-03, +-1.81005690458521380053e-03, +-1.87836956199671648374e-03, +-1.94555764270060572822e-03, +-2.01158361910792719829e-03, +-2.07641065585818058656e-03, +-2.14000263033844919519e-03, +-2.20232415277983682028e-03, +-2.26334058592000822788e-03, +-2.32301806422092246146e-03, +-2.38132351263152302820e-03, +-2.43822466488363524817e-03, +-2.49369008131333563458e-03, +-2.54768916619557087705e-03, +-2.60019218458394001450e-03, +-2.65117027864584945199e-03, +-2.70059548348453026811e-03, +-2.74844074243833736901e-03, +-2.79467992185021508675e-03, +-2.83928782529839322801e-03, +-2.88224020728095487592e-03, +-2.92351378634650351657e-03, +-2.96308625766492647960e-03, +-3.00093630502965393395e-03, +-3.03704361228680124254e-03, +-3.07138887418407363628e-03, +-3.10395380663392372531e-03, +-3.13472115638562150164e-03, +-3.16367471010103352980e-03, +-3.19079930282948481812e-03, +-3.21608082587721087059e-03, +-3.23950623406747337252e-03, +-3.26106355238757342555e-03, +-3.28074188201942212179e-03, +-3.29853140575076496377e-03, +-3.31442339276444199875e-03, +-3.32841020280317178778e-03, +-3.34048528970836431165e-03, +-3.35064320433112964454e-03, +-3.35887959681426418596e-03, +-3.36519121824467148246e-03, +-3.36957592167543267675e-03, +-3.37203266251754653349e-03, +-3.37256149830169856332e-03, +-3.37116358781047254292e-03, +-3.36784118958214327699e-03, +-3.36259765978729266434e-03, +-3.35543744947994172431e-03, +-3.34636610122527418040e-03, +-3.33539024510636330015e-03, +-3.32251759411259645072e-03, +-3.30775693891291596924e-03, +-3.29111814201739957125e-03, +-3.27261213133083796178e-03, +-3.25225089310266250384e-03, +-3.23004746427743008250e-03, +-3.20601592425105112044e-03, +-3.18017138603743105413e-03, +-3.15252998685158682818e-03, +-3.12310887811450286003e-03, +-3.09192621488647281444e-03, +-3.05900114473474978721e-03, +-3.02435379604281111970e-03, +-2.98800526576807482307e-03, +-2.94997760665555814816e-03, +-2.91029381391519391745e-03, +-2.86897781137080603100e-03, +-2.82605443708909163589e-03, +-2.78154942849715867623e-03, +-2.73548940699755568570e-03, +-2.68790186208995533074e-03, +-2.63881513500899191754e-03, +-2.58825840188760128782e-03, +-2.53626165645667129775e-03, +-2.48285569229048054193e-03, +-2.42807208460824822810e-03, +-2.37194317164358134745e-03, +-2.31450203559181158161e-03, +-2.25578248314654231793e-03, +-2.19581902563767547218e-03, +-2.13464685878131952071e-03, +-2.07230184205435888356e-03, +-2.00882047770541138920e-03, +-1.94423988941450141647e-03, +-1.87859780061385762441e-03, +-1.81193251248255946667e-03, +-1.74428288162779420063e-03, +-1.67568829746571096480e-03, +-1.60618865931505343768e-03, +-1.53582435321696704651e-03, +-1.46463622849387254017e-03, +-1.39266557406221786267e-03, +-1.31995409451166924308e-03, +-1.24654388596452171158e-03, +-1.17247741173051502755e-03, +-1.09779747777003140220e-03, +-1.02254720797977159512e-03, +-9.46770019316456627398e-04, +-8.70509596771090981941e-04, +-7.93809868209522859206e-04, +-7.16714979093283142790e-04, +-6.39269267095267379464e-04, +-5.61517236624901622949e-04, +-4.83503533277372383840e-04, +-4.05272918221601325187e-04, +-3.26870242541634718064e-04, +-2.48340421546139789206e-04, +-1.69728409060813500292e-04, +-9.10791717177389864102e-05, +-1.24376632583528602298e-05, + 6.61512011385834202077e-05, + 1.44642570486082041627e-04, + 2.22991683562456983764e-04, + 3.01153894413956873654e-04, + 3.79084697772648165047e-04, + 4.56739754373683643027e-04, + 5.34074916159440896482e-04, + 6.11046251354811493887e-04, + 6.87610069400060091790e-04, + 7.63722945726494719700e-04, + 8.39341746362165606193e-04, + 9.14423652352394037562e-04, + 9.88926183981333204245e-04, + 1.06280722478213824657e-03, + 1.13602504532090125416e-03, + 1.20853832674150526647e-03, + 1.28030618405801659317e-03, + 1.35128818918151915977e-03, + 1.42144439366839823308e-03, + 1.49073535117733935521e-03, + 1.55912213962240372468e-03, + 1.62656638300974010561e-03, + 1.69303027294565532589e-03, + 1.75847658980445606218e-03, + 1.82286872354303674040e-03, + 1.88617069415219075317e-03, + 1.94834717173209578771e-03, + 2.00936349618086648045e-03, + 2.06918569648611430298e-03, + 2.12778050960779879092e-03, + 2.18511539894190561298e-03, + 2.24115857235570323583e-03, + 2.29587899978361603334e-03, + 2.34924643037442331187e-03, + 2.40123140918023199666e-03, + 2.45180529337806233856e-03, + 2.50094026801512278949e-03, + 2.54860936126915377242e-03, + 2.59478645921546943742e-03, + 2.63944632009264395014e-03, + 2.68256458805902911827e-03, + 2.72411780643292029958e-03, + 2.76408343040847976832e-03, + 2.80243983924151687792e-03, + 2.83916634789766180597e-03, + 2.87424321815756868281e-03, + 2.90765166917223739917e-03, + 2.93937388746383842716e-03, + 2.96939303636573146555e-03, + 2.99769326489773184699e-03, + 3.02425971607121193627e-03, + 3.04907853462010837095e-03, + 3.07213687415372471712e-03, + 3.09342290372770093235e-03, + 3.11292581382988705480e-03, + 3.13063582177805889775e-03, + 3.14654417652693004295e-03, + 3.16064316288211652126e-03, + 3.17292610511905577922e-03, + 3.18338737000537549265e-03, + 3.19202236922536521438e-03, + 3.19882756120557767629e-03, + 3.20380045234103065510e-03, + 3.20693959762191095619e-03, + 3.20824460066048821466e-03, + 3.20771611311912148781e-03, + 3.20535583353980316201e-03, + 3.20116650557659455922e-03, + 3.19515191563226816363e-03, + 3.18731688990105815895e-03, + 3.17766729081954413250e-03, + 3.16621001292834072099e-03, + 3.15295297814715538495e-03, + 3.13790513046660092533e-03, + 3.12107643006004570677e-03, + 3.10247784681945935892e-03, + 3.08212135331927200924e-03, + 3.06001991721279766046e-03, + 3.03618749306580832173e-03, + 3.01063901363274712478e-03, + 2.98339038058057295921e-03, + 2.95445845466603060347e-03, + 2.92386104537267895939e-03, + 2.89161690001368777356e-03, + 2.85774569230700953987e-03, + 2.82226801043036334277e-03, + 2.78520534456247253682e-03, + 2.74658007391870816194e-03, + 2.70641545328861908917e-03, + 2.66473559908350773537e-03, + 2.62156547490237238143e-03, + 2.57693087662487496647e-03, + 2.53085841704014631939e-03, + 2.48337551002058860156e-03, + 2.43451035425012096355e-03, + 2.38429191651639985419e-03, + 2.33274991457697866704e-03, + 2.27991479960949847833e-03, + 2.22581773825620892956e-03, + 2.17049059427346612006e-03, + 2.11396590979692159534e-03, + 2.05627688623344091062e-03, + 1.99745736479101619609e-03, + 1.93754180665763118922e-03, + 1.87656527284175219002e-03, + 1.81456340368482097088e-03, + 1.75157239805861998823e-03, + 1.68762899225976484990e-03, + 1.62277043861255095177e-03, + 1.55703448379367948885e-03, + 1.49045934689147926804e-03, + 1.42308369721128166394e-03, + 1.35494663184088722126e-03, + 1.28608765298868091623e-03, + 1.21654664510756371255e-03, + 1.14636385181799576628e-03, + 1.07557985264340023011e-03, + 1.00423553957145047719e-03, + 9.32372093454700246948e-04, + 8.60030960264205842671e-04, + 7.87253827209889473632e-04, + 7.14082598740849215993e-04, + 6.40559372440761354631e-04, + 5.66726414830463851718e-04, + 4.92626137092837322433e-04, + 4.18301070733919581456e-04, + 3.43793843193061820010e-04, + 2.69147153417339558834e-04, + 1.94403747414189487621e-04, + 1.19606393795037383994e-04, + 4.47978593251173554416e-05, +-2.99791155070713611101e-05, +-1.04681840886644762128e-04, +-1.79267702021634553217e-04, +-2.53694183430834704039e-04, +-3.27918893156363931707e-04, +-4.01899586887169662890e-04, +-4.75594191979749616409e-04, +-5.48960831362461866741e-04, +-6.21957847309750270874e-04, +-6.94543825073334680428e-04, +-7.66677616355743358524e-04, +-8.38318362614142603174e-04, +-9.09425518181231052305e-04, +-9.79958873188954042791e-04, +-1.04987857628321295568e-03, +-1.11914515711671069299e-03, +-1.18771954860611567151e-03, +-1.25556310894265384798e-03, +-1.32263764334250685968e-03, +-1.38890542552527339500e-03, +-1.45432921890835268122e-03, +-1.51887229750536853490e-03, +-1.58249846651689705240e-03, +-1.64517208260199325476e-03, +-1.70685807381915056156e-03, +-1.76752195922558370811e-03, +-1.82712986812380161379e-03, +-1.88564855894518047276e-03, +-1.94304543775902804383e-03, +-1.99928857639786617534e-03, +-2.05434673018880555040e-03, +-2.10818935528026517312e-03, +-2.16078662555535365442e-03, +-2.21210944912246043961e-03, +-2.26212948437317816139e-03, +-2.31081915559989232653e-03, +-2.35815166816356804741e-03, +-2.40410102320373414084e-03, +-2.44864203188258338501e-03, +-2.49175032915539568928e-03, +-2.53340238705979841141e-03, +-2.57357552751657147824e-03, +-2.61224793463516640271e-03, +-2.64939866651717941329e-03, +-2.68500766655144999101e-03, +-2.71905577419492448452e-03, +-2.75152473523297344538e-03, +-2.78239721151426859513e-03, +-2.81165679015500094215e-03, +-2.83928799220713222809e-03, +-2.86527628078656016949e-03, +-2.88960806865697647852e-03, +-2.91227072526506090486e-03, +-2.93325258322398594105e-03, +-2.95254294424161442545e-03, +-2.97013208449042583406e-03, +-2.98601125941669364242e-03, +-3.00017270798633986159e-03, +-3.01260965636595103370e-03, +-3.02331632103655656429e-03, +-3.03228791133956007003e-03, +-3.03952063145331409857e-03, +-3.04501168179985596748e-03, +-3.04875925988140573583e-03, +-3.05076256054652829655e-03, +-3.05102177568631911103e-03, +-3.04953809336118561099e-03, +-3.04631369635912632385e-03, +-3.04135176018685343333e-03, +-3.03465645049527405624e-03, +-3.02623291994119940004e-03, +-3.01608730448767094895e-03, +-3.00422671914520132003e-03, +-2.99065925315701369377e-03, +-2.97539396463139928575e-03, +-2.95844087462449664011e-03, +-2.93981096067755893683e-03, +-2.91951614981275815730e-03, +-2.89756931099181044148e-03, +-2.87398424704220179990e-03, +-2.84877568605616283970e-03, +-2.82195927226750430117e-03, +-2.79355155641210087594e-03, +-2.76356998557781771697e-03, +-2.73203289255012551212e-03, +-2.69895948465983821080e-03, +-2.66436983213977395327e-03, +-2.62828485599736526648e-03, +-2.59072631541029923391e-03, +-2.55171679465334083972e-03, +-2.51127968956342670012e-03, +-2.46943919355152629105e-03, +-2.42622028316987056393e-03, +-2.38164870324227831086e-03, +-2.33575095156724138815e-03, +-2.28855426320279282948e-03, +-2.24008659434175860792e-03, +-2.19037660578759365432e-03, +-2.13945364604031535577e-03, +-2.08734773400249444888e-03, +-2.03408954131547529270e-03, +-1.97971037433622041798e-03, +-1.92424215576537916382e-03, +-1.86771740593727280343e-03, +-1.81016922378279560696e-03, +-1.75163126747638459545e-03, +-1.69213773477834518097e-03, +-1.63172334308366137785e-03, +-1.57042330918990852978e-03, +-1.50827332879462073199e-03, +-1.44530955573546056152e-03, +-1.38156858098379938318e-03, +-1.31708741140545613178e-03, +-1.25190344829938021362e-03, +-1.18605446572830376673e-03, +-1.11957858865226037894e-03, +-1.05251427087881964557e-03, +-9.84900272842268017723e-04, +-9.16775639224670039346e-04, +-8.48179676431708726506e-04, +-7.79151929936275832941e-04, +-7.09732161502877071865e-04, +-6.39960326305943926796e-04, +-5.69876549955214807899e-04, +-4.99521105441456947371e-04, +-4.28934390015275781964e-04, +-3.58156902013427212109e-04, +-2.87229217644762195236e-04, +-2.16191967749079295199e-04, +-1.45085814543370996213e-04, +-7.39514283676623567637e-05, +-2.82946444373383170840e-06, + 6.82394603388270838424e-05, + 1.39214790597688687322e-04, + 2.10056055579472498182e-04, + 2.80722892215425577894e-04, + 3.51175068097857930472e-04, + 4.21372504364276407804e-04, + 4.91275298476219653143e-04, + 5.60843746879846811494e-04, + 6.30038367535434352430e-04, + 6.98819922302998017792e-04, + 7.67149439171379990757e-04, + 8.34988234318114982448e-04, + 9.02297933988172430955e-04, + 9.69040496177550657667e-04, + 1.03517823211224553603e-03, + 1.10067382750771766003e-03, + 1.16549036359852469825e-03, + 1.22959133792568584519e-03, + 1.29294068487057216450e-03, + 1.35550279592269035112e-03, + 1.41724253967147762606e-03, + 1.47812528150976737508e-03, + 1.53811690303841180558e-03, + 1.59718382116064388891e-03, + 1.65529300685696286952e-03, + 1.71241200362764220237e-03, + 1.76850894559496454178e-03, + 1.82355257525374002750e-03, + 1.87751226086060006570e-03, + 1.93035801345242652959e-03, + 1.98206050348444977674e-03, + 2.03259107707881624474e-03, + 2.08192177187458684826e-03, + 2.13002533247049928231e-03, + 2.17687522545193749141e-03, + 2.22244565399375279199e-03, + 2.26671157203132793423e-03, + 2.30964869799124257813e-03, + 2.35123352807515510060e-03, + 2.39144334908883470295e-03, + 2.43025625080947474746e-03, + 2.46765113788514900417e-03, + 2.50360774125928499736e-03, + 2.53810662911404865891e-03, + 2.57112921732736803004e-03, + 2.60265777943738526798e-03, + 2.63267545610921865559e-03, + 2.66116626409909065240e-03, + 2.68811510471097300096e-03, + 2.71350777174133141537e-03, + 2.73733095890790929794e-03, + 2.75957226675855411477e-03, + 2.78022020905670675522e-03, + 2.79926421864012953122e-03, + 2.81669465275010289657e-03, + 2.83250279782839122292e-03, + 2.84668087377948006433e-03, + 2.85922203769641003479e-03, + 2.87012038704810915068e-03, + 2.87937096232720231986e-03, + 2.88696974915680091081e-03, + 2.89291367985583221592e-03, + 2.89720063446215116837e-03, + 2.89982944121351280883e-03, + 2.90079987648640116524e-03, + 2.90011266419314345591e-03, + 2.89776947463821947862e-03, + 2.89377292283466130279e-03, + 2.88812656628207459208e-03, + 2.88083490220782285907e-03, + 2.87190336427351573453e-03, + 2.86133831874895577796e-03, + 2.84914706015623872201e-03, + 2.83533780638680265804e-03, + 2.81991969329480843959e-03, + 2.80290276877008005807e-03, + 2.78429798629470500945e-03, + 2.76411719798695795433e-03, + 2.74237314713741920855e-03, + 2.71907946024148436046e-03, + 2.69425063853359278432e-03, + 2.66790204902807304155e-03, + 2.64004991507226990932e-03, + 2.61071130641776349285e-03, + 2.57990412881558845576e-03, + 2.54764711314187488125e-03, + 2.51395980406045370728e-03, + 2.47886254822925330629e-03, + 2.44237648205756618242e-03, + 2.40452351902155575872e-03, + 2.36532633654565121670e-03, + 2.32480836245730617881e-03, + 2.28299376102392148624e-03, + 2.23990741857956789096e-03, + 2.19557492874996457166e-03, + 2.15002257728523623811e-03, + 2.10327732650867141317e-03, + 2.05536679939101810111e-03, + 2.00631926325935171576e-03, + 1.95616361315094399245e-03, + 1.90492935482074665296e-03, + 1.85264658741337391243e-03, + 1.79934598580928591972e-03, + 1.74505878265607109780e-03, + 1.68981675009393424863e-03, + 1.63365218118834728926e-03, + 1.57659787107846988304e-03, + 1.51868709785361530318e-03, + 1.45995360316849881639e-03, + 1.40043157260870475105e-03, + 1.34015561581719584022e-03, + 1.27916074639499105850e-03, + 1.21748236158513117693e-03, + 1.15515622175421423141e-03, + 1.09221842968186999730e-03, + 1.02870540967075650360e-03, + 9.64653886488606908747e-04, + 9.00100864155625344717e-04, + 8.35083604587965547955e-04, + 7.69639606110740720837e-04, + 7.03806581852404870327e-04, + 6.37622438033560502181e-04, + 5.71125252161062339600e-04, + 5.04353251142653142593e-04, + 4.37344789331979761672e-04, + 3.70138326518233945050e-04, + 3.02772405872475636971e-04, + 2.35285631863361933882e-04, + 1.67716648154917370023e-04, + 1.00104115498995325769e-04, + 3.24866896350573601776e-05, +-3.50970007900988141157e-05, +-1.02608376270067855503e-04, +-1.70008928441366460871e-04, +-2.37260242028708613496e-04, +-3.04324016719330044459e-04, +-3.71162088955520488940e-04, +-4.37736453631852389604e-04, +-5.04009285684787491054e-04, +-5.69942961563439155249e-04, +-6.35500080568199678457e-04, +-7.00643486045153811477e-04, +-7.65336286425376288202e-04, +-8.29541876096107381675e-04, +-8.93223956092492241653e-04, +-9.56346554598112288600e-04, +-1.01887404724274391321e-03, +-1.08077117718591146113e-03, +-1.14200307497491554062e-03, +-1.20253527816616481716e-03, +-1.26233375069880002922e-03, +-1.32136490200969610419e-03, +-1.37959560587909771390e-03, +-1.43699321899669958842e-03, +-1.49352559923677944212e-03, +-1.54916112363357523669e-03, +-1.60386870604548384400e-03, +-1.65761781449959505821e-03, +-1.71037848820545417342e-03, +-1.76212135422995869009e-03, +-1.81281764382279454370e-03, +-1.86243920838466956759e-03, +-1.91095853506853020909e-03, +-1.95834876200555885878e-03, +-2.00458369314743039755e-03, +-2.04963781271666782222e-03, +-2.09348629925715234990e-03, +-2.13610503927705698904e-03, +-2.17747064047668550252e-03, +-2.21756044455409095234e-03, +-2.25635253958129250451e-03, +-2.29382577194474921237e-03, +-2.32995975784284353738e-03, +-2.36473489433514528352e-03, +-2.39813236993652442383e-03, +-2.43013417475133235504e-03, +-2.46072311014130552798e-03, +-2.48988279792284553787e-03, +-2.51759768908801960866e-03, +-2.54385307204538875167e-03, +-2.56863508037586708854e-03, +-2.59193070009968232204e-03, +-2.61372777645068558178e-03, +-2.63401502015447874783e-03, +-2.65278201320723284670e-03, +-2.67001921415216522324e-03, +-2.68571796285115840450e-03, +-2.69987048474913367627e-03, +-2.71246989462914107200e-03, +-2.72351019985639722365e-03, +-2.73298630310992796480e-03, +-2.74089400460035331406e-03, +-2.74723000377341628614e-03, +-2.75199190049820862497e-03, +-2.75517819574011687753e-03, +-2.75678829171838255668e-03, +-2.75682249154861379672e-03, +-2.75528199837085348636e-03, +-2.75216891396407340939e-03, +-2.74748623684835597061e-03, +-2.74123785987614347961e-03, +-2.73342856731443109575e-03, +-2.72406403141984849309e-03, +-2.71315080850912087457e-03, +-2.70069633452742902113e-03, +-2.68670892011764299301e-03, +-2.67119774519362050691e-03, +-2.65417285302107976847e-03, +-2.63564514380968837812e-03, +-2.61562636782076193137e-03, +-2.59412911799431541299e-03, +-2.57116682210057310998e-03, +-2.54675373442056615300e-03, +-2.52090492696093165098e-03, +-2.49363628020824292311e-03, +-2.46496447342882049614e-03, +-2.43490697451945311766e-03, +-2.40348202941552966175e-03, +-2.37070865106279527260e-03, +-2.33660660795969189057e-03, +-2.30119641227629137537e-03, +-2.26449930755836560670e-03, +-2.22653725602254669996e-03, +-2.18733292545093653547e-03, +-2.14690967569279187940e-03, +-2.10529154478122275743e-03, +-2.06250323467321427379e-03, +-2.01857009662140480036e-03, +-1.97351811618623213668e-03, +-1.92737389789730405483e-03, +-1.88016464957305564146e-03, +-1.83191816630788313451e-03, +-1.78266281413625186578e-03, +-1.73242751338296301945e-03, +-1.68124172171028180012e-03, +-1.62913541687057699184e-03, +-1.57613907917578230551e-03, +-1.52228367369270224489e-03, +-1.46760063217584650445e-03, +-1.41212183474704526358e-03, +-1.35587959133381627010e-03, +-1.29890662287597178325e-03, +-1.24123604231228925124e-03, +-1.18290133535796414613e-03, +-1.12393634108397949545e-03, +-1.06437523230972224016e-03, +-1.00425249582011886888e-03, +-9.43602912418799676629e-04, +-8.82461536828750689118e-04, +-8.20863677452122195502e-04, +-7.58844876000883323576e-04, +-6.96440887009666122730e-04, +-6.33687657243661695526e-04, +-5.70621305011907871928e-04, +-5.07278099399384235432e-04, +-4.43694439428299856887e-04, +-3.79906833162163342851e-04, +-3.15951876763069777060e-04, +-2.51866233515757136346e-04, +-1.87686612828893105692e-04, +-1.23449749226707587929e-04, +-5.91923813425564756662e-05, + 5.04876907352367874530e-06, + 6.92370181212766702379e-05, + 1.33335740678748094525e-04, + 1.97308391280935971606e-04, + 2.61118524936681541647e-04, + 3.24729817871949365607e-04, + 3.88106088187632042828e-04, + 4.51211316420591741425e-04, + 5.14009665995129438193e-04, + 5.76465503554872784643e-04, + 6.38543419161980286940e-04, + 7.00208246353774092785e-04, + 7.61425082043918786609e-04, + 8.22159306257914143483e-04, + 8.82376601691744100360e-04, + 9.42042973081658576232e-04, + 1.00112476637558055551e-03, + 1.05958868769426566188e-03, + 1.11740182207199128042e-03, + 1.17453165196615329918e-03, + 1.23094607552536169578e-03, + 1.28661342460581668880e-03, + 1.34150248252584160767e-03, + 1.39558250154863013048e-03, + 1.44882322008345787619e-03, + 1.50119487959565409141e-03, + 1.55266824121634344422e-03, + 1.60321460204141557661e-03, + 1.65280581111278590707e-03, + 1.70141428507094454904e-03, + 1.74901302347134422581e-03, + 1.79557562375571026954e-03, + 1.84107629587033070663e-03, + 1.88548987652245613779e-03, + 1.92879184306802143982e-03, + 1.97095832702225181102e-03, + 2.01196612718603342132e-03, + 2.05179272238057222588e-03, + 2.09041628378424165433e-03, + 2.12781568686330919971e-03, + 2.16397052289168034464e-03, + 2.19886111005235902402e-03, + 2.23246850411500585495e-03, + 2.26477450868369997727e-03, + 2.29576168500963484834e-03, + 2.32541336136273067009e-03, + 2.35371364195842858874e-03, + 2.38064741543364153872e-03, + 2.40620036286810995776e-03, + 2.43035896534666076563e-03, + 2.45311051105864775732e-03, + 2.47444310193039576293e-03, + 2.49434565978784222526e-03, + 2.51280793204573761265e-03, + 2.52982049692079043884e-03, + 2.54537476816590630541e-03, + 2.55946299932366090960e-03, + 2.57207828749620934228e-03, + 2.58321457663059431131e-03, + 2.59286666031753468623e-03, + 2.60103018410256332446e-03, + 2.60770164730860518412e-03, + 2.61287840436931441054e-03, + 2.61655866567281477839e-03, + 2.61874149791569560408e-03, + 2.61942682396747910170e-03, + 2.61861542224603579751e-03, + 2.61630892560461673912e-03, + 2.61250981973162573271e-03, + 2.60722144106427262261e-03, + 2.60044797421789914901e-03, + 2.59219444893257419671e-03, + 2.58246673653929684211e-03, + 2.57127154594804412449e-03, + 2.55861641916043432848e-03, + 2.54450972630984205078e-03, + 2.52896066023234862910e-03, + 2.51197923057173110040e-03, + 2.49357625742245613346e-03, + 2.47376336451454867035e-03, + 2.45255297194462698260e-03, + 2.42995828845761051989e-03, + 2.40599330328385152544e-03, + 2.38067277753669032450e-03, + 2.35401223517576205571e-03, + 2.32602795354144506468e-03, + 2.29673695346632733560e-03, + 2.26615698896941598212e-03, + 2.23430653653983570320e-03, + 2.20120478401572821497e-03, + 2.16687161906578855050e-03, + 2.13132761727950238717e-03, + 2.09459402987411226829e-03, + 2.05669277102470907798e-03, + 2.01764640482596626161e-03, + 1.97747813189227050409e-03, + 1.93621177560486024995e-03, + 1.89387176801387676663e-03, + 1.85048313540364336473e-03, + 1.80607148352974512806e-03, + 1.76066298253653116292e-03, + 1.71428435156398707023e-03, + 1.66696284305293466847e-03, + 1.61872622675783670206e-03, + 1.56960277347651289311e-03, + 1.51962123850639114868e-03, + 1.46881084483655192582e-03, + 1.41720126608627463617e-03, + 1.36482260919915132126e-03, + 1.31170539690283571681e-03, + 1.25788054994554945182e-03, + 1.20337936911878791608e-03, + 1.14823351707673366670e-03, + 1.09247499996376496584e-03, + 1.03613614885946750573e-03, + 9.79249601052817287769e-04, + 9.21848281156024094984e-04, + 8.63965382068984373391e-04, + 8.05634345805350776497e-04, + 7.46888844191288077054e-04, + 6.87762759448037191978e-04, + 6.28290164669462083795e-04, + 5.68505304205851338083e-04, + 5.08442573965285464499e-04, + 4.48136501643423001973e-04, + 3.87621726894541677056e-04, + 3.26932981452717592256e-04, + 2.66105069217038663586e-04, + 2.05172846310758418649e-04, + 1.44171201126380563911e-04, + 8.31350343675788742547e-05, + 2.20992391004467811420e-05, +-3.89013191759796718742e-05, +-9.98318224274676811183e-05, +-1.60657519939763258031e-04, +-2.21343748119307129384e-04, +-2.81855950229735626421e-04, +-3.42159696050412485968e-04, +-4.02220701448342615129e-04, +-4.62004847850846784695e-04, +-5.21478201608437975934e-04, +-5.80607033236791485534e-04, +-6.39357836527398360783e-04, +-6.97697347514598421869e-04, +-7.55592563290745562223e-04, +-8.13010760656402635231e-04, +-8.69919514596503569252e-04, +-9.26286716571595044288e-04, +-9.82080592613842522434e-04, +-1.03726972121798914454e-03, +-1.09182305101626067265e-03, +-1.14570991822856215955e-03, +-1.19890006387727231750e-03, +-1.25136365075697989814e-03, +-1.30307128015050440427e-03, +-1.35399400828092701665e-03, +-1.40410336249047434758e-03, +-1.45337135713807666729e-03, +-1.50177050920588701921e-03, +-1.54927385360641156620e-03, +-1.59585495818171090726e-03, +-1.64148793838632899543e-03, +-1.68614747164579970896e-03, +-1.72980881138278994556e-03, +-1.77244780070314389073e-03, +-1.81404088573422256521e-03, +-1.85456512860821833531e-03, +-1.89399822008349183119e-03, +-1.93231849179640994586e-03, +-1.96950492813784778720e-03, +-2.00553717774697637041e-03, +-2.04039556461697076800e-03, +-2.07406109880563802386e-03, +-2.10651548674606337030e-03, +-2.13774114115079620635e-03, +-2.16772119050517375963e-03, +-2.19643948814392904120e-03, +-2.22388062090664783907e-03, +-2.25002991736723010133e-03, +-2.27487345563314293309e-03, +-2.29839807071028278881e-03, +-2.32059136142953635965e-03, +-2.34144169693150825881e-03, +-2.36093822270602455432e-03, +-2.37907086618326232483e-03, +-2.39583034187382639194e-03, +-2.41120815605485715877e-03, +-2.42519661100030125764e-03, +-2.43778880875283833138e-03, +-2.44897865443608397581e-03, +-2.45876085910516064756e-03, +-2.46713094213460307561e-03, +-2.47408523314259810866e-03, +-2.47962087345062007909e-03, +-2.48373581707827476711e-03, +-2.48642883127294603979e-03, +-2.48769949657436095780e-03, +-2.48754820641444327964e-03, +-2.48597616625299746435e-03, +-2.48298539225010744813e-03, +-2.47857870947639034181e-03, +-2.47275974966242300529e-03, +-2.46553294848908619713e-03, +-2.45690354242066423887e-03, +-2.44687756508286339413e-03, +-2.43546184318826561266e-03, +-2.42266399201183056655e-03, +-2.40849241041931304286e-03, +-2.39295627545196452554e-03, +-2.37606553647086871789e-03, +-2.35783090886447369364e-03, +-2.33826386732362018900e-03, +-2.31737663868781000251e-03, +-2.29518219436743642001e-03, +-2.27169424234655459999e-03, +-2.24692721877107516593e-03, +-2.22089627912754614472e-03, +-2.19361728901783497453e-03, +-2.16510681453538442881e-03, +-2.13538211224875490099e-03, +-2.10446111879856838367e-03, +-2.07236244011410305002e-03, +-2.03910534025573964012e-03, +-2.00470972989070942219e-03, +-1.96919615440774254875e-03, +-1.93258578167894933507e-03, +-1.89490038947546677803e-03, +-1.85616235254462648083e-03, +-1.81639462935595909568e-03, +-1.77562074852458812169e-03, +-1.73386479491910482434e-03, +-1.69115139546278155785e-03, +-1.64750570463616328315e-03, +-1.60295338968996568633e-03, +-1.55752061557586866242e-03, +-1.51123402960583901912e-03, +-1.46412074584717846748e-03, +-1.41620832926347625658e-03, +-1.36752477961040201301e-03, +-1.31809851509572971071e-03, +-1.26795835581320162112e-03, +-1.21713350695978428199e-03, +-1.16565354184613783825e-03, +-1.11354838471016369394e-03, +-1.06084829334356697123e-03, +-1.00758384154156217620e-03, +-9.53785901385918667879e-04, +-8.99485625371226915105e-04, +-8.44714428385682711276e-04, +-7.89503969555520172287e-04, +-7.33886133964478507875e-04, +-6.77893014258843288299e-04, +-6.21556892147806690219e-04, +-5.64910219810742480866e-04, +-5.07985601222065157219e-04, +-4.50815773403514705956e-04, +-3.93433587615536740044e-04, +-3.35871990498167328609e-04, +-2.78164005172315390892e-04, +-2.20342712312250957329e-04, +-1.62441231200158043299e-04, +-1.04492700773580143945e-04, +-4.65302606765986506319e-05, + 1.14129676744331286925e-05, + 6.93038999997214335376e-05, + 1.27109508029058849467e-04, + 1.84796838327256962358e-04, + 2.42333031062709627164e-04, + 2.99685338706966609285e-04, + 3.56821144656121883639e-04, + 4.13707981761937345928e-04, + 4.70313550763611239701e-04, + 5.26605738608316954405e-04, + 5.82552636651546872429e-04, + 6.38122558725952955180e-04, + 6.93284059068853498672e-04, + 7.48005950098214232938e-04, + 8.02257320027068118913e-04, + 8.56007550306428347843e-04, + 9.09226332886875140971e-04, + 9.61883687289077828758e-04, + 1.01394997747366656139e-03, + 1.06539592850096254475e-03, + 1.11619264297115245756e-03, + 1.16631161723606104411e-03, + 1.21572475737255643845e-03, + 1.26440439490956338907e-03, + 1.31232330229981257463e-03, + 1.35945470812689692131e-03, + 1.40577231203991388428e-03, + 1.45125029940738111550e-03, + 1.49586335568145547929e-03, + 1.53958668046561540123e-03, + 1.58239600127717565045e-03, + 1.62426758699731900969e-03, + 1.66517826100116947581e-03, + 1.70510541396065628053e-03, + 1.74402701631310862347e-03, + 1.78192163038870358960e-03, + 1.81876842219015340089e-03, + 1.85454717281811399567e-03, + 1.88923828953608337507e-03, + 1.92282281646894998711e-03, + 1.95528244492883035086e-03, + 1.98659952336315047752e-03, + 2.01675706691958021854e-03, + 2.04573876662207838895e-03, + 2.07352899815367369349e-03, + 2.10011283024123633634e-03, + 2.12547603263724084119e-03, + 2.14960508369503545609e-03, + 2.17248717753304627920e-03, + 2.19411023078435168249e-03, + 2.21446288892813546861e-03, + 2.23353453219959832005e-03, + 2.25131528107543575634e-03, + 2.26779600133197476938e-03, + 2.28296830867344077709e-03, + 2.29682457292811666866e-03, + 2.30935792181020602132e-03, + 2.32056224424581451771e-03, + 2.33043219326110580616e-03, + 2.33896318843187242878e-03, + 2.34615141789296230077e-03, + 2.35199383990705723768e-03, + 2.35648818399214129982e-03, + 2.35963295160742693446e-03, + 2.36142741639763483266e-03, + 2.36187162399587079545e-03, + 2.36096639138556364801e-03, + 2.35871330582219018365e-03, + 2.35511472331569049476e-03, + 2.35017376667488861117e-03, + 2.34389432311526155553e-03, + 2.33628104143192337830e-03, + 2.32733932873959879425e-03, + 2.31707534678196646130e-03, + 2.30549600781271638028e-03, + 2.29260897005103539067e-03, + 2.27842263271448887407e-03, + 2.26294613063242897391e-03, + 2.24618932844335367563e-03, + 2.22816281437991214193e-03, + 2.20887789364531414785e-03, + 2.18834658138542404587e-03, + 2.16658159526062063169e-03, + 2.14359634762239202599e-03, + 2.11940493729897636022e-03, + 2.09402214099534654534e-03, + 2.06746340431283176509e-03, + 2.03974483239339685059e-03, + 2.01088318019464239519e-03, + 1.98089584240138030097e-03, + 1.94980084297942022308e-03, + 1.91761682437821957652e-03, + 1.88436303638870564399e-03, + 1.85005932466290553585e-03, + 1.81472611890221816218e-03, + 1.77838442072136338791e-03, + 1.74105579119516714129e-03, + 1.70276233809558063745e-03, + 1.66352670282644788877e-03, + 1.62337204706380910935e-03, + 1.58232203910926546089e-03, + 1.54040083996521471633e-03, + 1.49763308913912528489e-03, + 1.45404389018587740061e-03, + 1.40965879599663345551e-03, + 1.36450379384215388784e-03, + 1.31860529018035092276e-03, + 1.27199009523587059159e-03, + 1.22468540736182600857e-03, + 1.17671879719162628813e-03, + 1.12811819159096510083e-03, + 1.07891185741895972300e-03, + 1.02912838510792908377e-03, + 9.78796672071337260299e-04, + 9.27945905949520053434e-04, + 8.76605547702895976370e-04, + 8.24805314562447990448e-04, + 7.72575162847333337356e-04, + 7.19945270659597320352e-04, + 6.66946020465617123510e-04, + 6.13607981575178514436e-04, + 5.59961892527424567705e-04, + 5.06038643393795593145e-04, + 4.51869258009022058478e-04, + 3.97484876139576502260e-04, + 3.42916735599798760004e-04, + 2.88196154326876910479e-04, + 2.33354512423656609626e-04, + 1.78423234180534077487e-04, + 1.23433770086348173567e-04, + 6.84175788386079240409e-05, + 1.34061093633470900020e-05, +-4.15692171451308774711e-05, +-9.64770251543709412689e-05, +-1.51286002683524126340e-04, +-2.05964919142553784092e-04, +-2.60482643110675150724e-04, +-3.14808160044301459275e-04, +-3.68910589903529524333e-04, +-4.22759204688063789518e-04, +-4.76323445872630008881e-04, +-5.29572941731087281150e-04, +-5.82477524540275987987e-04, +-6.35007247653846472989e-04, +-6.87132402435543243602e-04, +-7.38823535043645019879e-04, +-7.90051463056118570549e-04, +-8.40787291927532235911e-04, +-8.91002431268342548823e-04, +-9.40668610937454570224e-04, +-9.89757896938941268347e-04, +-1.03824270711407040668e-03, +-1.08609582661974403764e-03, +-1.13329042318477575535e-03, +-1.17980006213536797732e-03, +-1.22559872118147396639e-03, +-1.27066080495571239080e-03, +-1.31496115929677771621e-03, +-1.35847508526934588474e-03, +-1.40117835291272236839e-03, +-1.44304721471052890651e-03, +-1.48405841877397026707e-03, +-1.52418922173162092390e-03, +-1.56341740131789178406e-03, +-1.60172126865418262831e-03, +-1.63907968021530041879e-03, +-1.67547204947450902382e-03, +-1.71087835822147623158e-03, +-1.74527916754618566374e-03, +-1.77865562848291466208e-03, +-1.81098949230900328755e-03, +-1.84226312049221930059e-03, +-1.87245949428157002978e-03, +-1.90156222393633397329e-03, +-1.92955555758831764739e-03, +-1.95642438973256090409e-03, +-1.98215426934193923725e-03, +-2.00673140760134708499e-03, +-2.03014268525729749126e-03, +-2.05237565957906665723e-03, +-2.07341857092785582239e-03, +-2.09326034893013391766e-03, +-2.11189061825244484699e-03, +-2.12929970397441031132e-03, +-2.14547863655709580497e-03, +-2.16041915640460824299e-03, +-2.17411371801621297953e-03, +-2.18655549372708977660e-03, +-2.19773837703605891963e-03, +-2.20765698551850719430e-03, +-2.21630666332326515741e-03, +-2.22368348325234152507e-03, +-2.22978424842263864281e-03, +-2.23460649350903971591e-03, +-2.23814848556852345751e-03, +-2.24040922444509972219e-03, +-2.24138844275575217432e-03, +-2.24108660545765600580e-03, +-2.23950490899731862252e-03, +-2.23664528004239790415e-03, +-2.23251037379732560767e-03, +-2.22710357190395455765e-03, +-2.22042897992885809519e-03, +-2.21249142443891893065e-03, +-2.20329644966735498784e-03, +-2.19285031377223701976e-03, +-2.18115998469021890940e-03, +-2.16823313558786156391e-03, +-2.15407813991372407841e-03, +-2.13870406605424102225e-03, +-2.12212067159678200237e-03, +-2.10433839720351734126e-03, +-2.08536836009985638782e-03, +-2.06522234718151120880e-03, +-2.04391280774443356502e-03, +-2.02145284584207300324e-03, +-1.99785621227463244462e-03, +-1.97313729621508525403e-03, +-1.94731111647731430260e-03, +-1.92039331243139960170e-03, +-1.89240013457138639766e-03, +-1.86334843474168982726e-03, +-1.83325565602760116347e-03, +-1.80213982231590299880e-03, +-1.77001952753231455231e-03, +-1.73691392456148648374e-03, +-1.70284271385666495340e-03, +-1.66782613174552775577e-03, +-1.63188493843921685576e-03, +-1.59504040575159230717e-03, +-1.55731430453603003801e-03, +-1.51872889184707753063e-03, +-1.47930689783463205529e-03, +-1.43907151237822393368e-03, +-1.39804637146942033893e-03, +-1.35625554334995140730e-03, +-1.31372351441438970504e-03, +-1.27047517488496053938e-03, +-1.22653580426682431471e-03, +-1.18193105659301824634e-03, +-1.13668694546695714549e-03, +-1.09082982891158691320e-03, +-1.04438639403357878127e-03, +-9.97383641512322120098e-04, +-9.49848869921641547967e-04, +-9.01809659894115857315e-04, +-8.53293858136809635351e-04, +-8.04329561308134524146e-04, +-7.54945099763940303053e-04, +-7.05169021184243009770e-04, +-6.55030074088056891990e-04, +-6.04557191246998305335e-04, +-5.53779473006872830811e-04, +-5.02726170526861184003e-04, +-4.51426668945984269337e-04, +-3.99910470486500410799e-04, +-3.48207177503949535848e-04, +-2.96346475493580014358e-04, +-2.44358116062887999707e-04, +-1.92271899880109192792e-04, +-1.40117659608033219131e-04, +-8.79252428338516013985e-05, +-3.57244950035476513677e-05, + 1.64547576285501491889e-05, + 6.85827250253236744533e-05, + 1.20629670358623862633e-04, + 1.72565926956682051847e-04, + 2.24361915197526828099e-04, + 2.75988159339660512649e-04, + 3.27415304279563739234e-04, + 3.78614132226878525450e-04, + 4.29555579287748767834e-04, + 4.80210751946913818114e-04, + 5.30550943439215389429e-04, + 5.80547650001254260735e-04, + 6.30172586994006268639e-04, + 6.79397704887282211095e-04, + 7.28195205096961932327e-04, + 7.76537555666397547385e-04, + 8.24397506782311470346e-04, + 8.71748106117578472167e-04, + 9.18562713991485446999e-04, + 9.64815018338932312708e-04, + 1.01047904948097389682e-03, + 1.05552919468725366070e-03, + 1.09994021252330666759e-03, + 1.14368724697360216180e-03, + 1.18674584133354179757e-03, + 1.22909195186185872875e-03, + 1.27070196118612760081e-03, + 1.31155269145389143971e-03, + 1.35162141722206191954e-03, + 1.39088587807745310380e-03, + 1.42932429098146206170e-03, + 1.46691536233205330891e-03, + 1.50363829973637033906e-03, + 1.53947282348746166021e-03, + 1.57439917773903939602e-03, + 1.60839814137149570566e-03, + 1.64145103854408192304e-03, + 1.67353974892666301950e-03, + 1.70464671760622052225e-03, + 1.73475496466189292762e-03, + 1.76384809440413852129e-03, + 1.79191030427224506048e-03, + 1.81892639338610754944e-03, + 1.84488177074716187820e-03, + 1.86976246308427976328e-03, + 1.89355512234033978962e-03, + 1.91624703279555906599e-03, + 1.93782611782377474016e-03, + 1.95828094627808731512e-03, + 1.97760073850255548022e-03, + 1.99577537196677290074e-03, + 2.01279538652043366379e-03, + 2.02865198926522683279e-03, + 2.04333705904144154533e-03, + 2.05684315052714027094e-03, + 2.06916349794801935486e-03, + 2.08029201839576892777e-03, + 2.09022331475368274706e-03, + 2.09895267822806817423e-03, + 2.10647609048419644576e-03, + 2.11279022538611149090e-03, + 2.11789245033947156824e-03, + 2.12178082723701432605e-03, + 2.12445411300643061461e-03, + 2.12591175976064054517e-03, + 2.12615391455073503985e-03, + 2.12518141872201785439e-03, + 2.12299580687382158026e-03, + 2.11959930542408034673e-03, + 2.11499483077969572045e-03, + 2.10918598711416641414e-03, + 2.10217706375393116602e-03, + 2.09397303217547263096e-03, + 2.08457954261486583247e-03, + 2.07400292029235070942e-03, + 2.06225016125420471461e-03, + 2.04932892783467367551e-03, + 2.03524754374076423044e-03, + 2.02001498876324889209e-03, + 2.00364089311688611111e-03, + 1.98613553141360494464e-03, + 1.96750981627234018331e-03, + 1.94777529156955181953e-03, + 1.92694412533416631859e-03, + 1.90502910229207360684e-03, + 1.88204361606385760751e-03, + 1.85800166102108787677e-03, + 1.83291782380585869562e-03, + 1.80680727451872601141e-03, + 1.77968575758040859630e-03, + 1.75156958227263453466e-03, + 1.72247561296389362258e-03, + 1.69242125902588661998e-03, + 1.66142446444668846067e-03, + 1.62950369714685090912e-03, + 1.59667793800455284220e-03, + 1.56296666959689989698e-03, + 1.52838986466322470682e-03, + 1.49296797429780258443e-03, + 1.45672191587891005325e-03, + 1.41967306074082186274e-03, + 1.38184322159656857235e-03, + 1.34325463971886609367e-03, + 1.30392997188612789518e-03, + 1.26389227710180132407e-03, + 1.22316500309457604385e-03, + 1.18177197260732505350e-03, + 1.13973736948289701074e-03, + 1.09708572455475997058e-03, + 1.05384190135080434668e-03, + 1.01003108161856368016e-03, + 9.65678750680322895046e-04, + 9.20810682626568323406e-04, + 8.75452925356471657603e-04, + 8.29631785473724093875e-04, + 7.83373813047290703040e-04, + 7.36705786244772238558e-04, + 6.89654695848395987885e-04, + 6.42247729661416769283e-04, + 5.94512256815164243616e-04, + 5.46475811984593212202e-04, + 4.98166079522630966640e-04, + 4.49610877521255665294e-04, + 4.00838141809322300816e-04, + 3.51875909896002484617e-04, + 3.02752304869100116388e-04, + 2.53495519257492917930e-04, + 2.04133798866942952959e-04, + 1.54695426598542049934e-04, + 1.05208706259043055812e-04, + 5.57019463723481029365e-05, + 6.20344400145258794332e-06, +-4.32585314102668224909e-05, +-9.26557541683200246944e-05, +-1.41960058418968396079e-04, +-1.91143354193288721741e-04, +-2.40177643395536041327e-04, +-2.89035035725425371294e-04, +-3.37687764526517215750e-04, +-3.86108202550481673879e-04, +-4.34268877629523874194e-04, +-4.82142488247218933394e-04, +-5.29701918999288495597e-04, +-5.76920255935507784832e-04, +-6.23770801774083051734e-04, +-6.70227090979901799633e-04, +-7.16262904698151416615e-04, +-7.61852285534880065317e-04, +-8.06969552176199341267e-04, +-8.51589313837822735331e-04, +-8.95686484537168122258e-04, +-9.39236297179238443025e-04, +-9.82214317449158023227e-04, +-1.02459645750355089928e-03, +-1.06635898945237213818e-03, +-1.10747855862441241769e-03, +-1.14793219660866787669e-03, +-1.18769733406468773300e-03, +-1.22675181329402055441e-03, +-1.26507390056672754976e-03, +-1.30264229819540794213e-03, +-1.33943615635037714499e-03, +-1.37543508460907315874e-03, +-1.41061916323427321250e-03, +-1.44496895417330940836e-03, +-1.47846551177379173514e-03, +-1.51109039320902033797e-03, +-1.54282566860766408127e-03, +-1.57365393088206863802e-03, +-1.60355830525010312551e-03, +-1.63252245844455485396e-03, +-1.66053060760636725206e-03, +-1.68756752885559392630e-03, +-1.71361856553621906898e-03, +-1.73866963613010581773e-03, +-1.76270724183600984401e-03, +-1.78571847380921077363e-03, +-1.80769102005840930254e-03, +-1.82861317199587238881e-03, +-1.84847383063749628497e-03, +-1.86726251244936523530e-03, +-1.88496935483824668706e-03, +-1.90158512128234106521e-03, +-1.91710120610045944671e-03, +-1.93150963885675339658e-03, +-1.94480308839885176336e-03, +-1.95697486652746934985e-03, +-1.96801893129561937881e-03, +-1.97792988993586308158e-03, +-1.98670300141425048082e-03, +-1.99433417860976971991e-03, +-2.00081999011835322613e-03, +-2.00615766168074291520e-03, +-2.01034507723373218405e-03, +-2.01338077958435448037e-03, +-2.01526397070713597648e-03, +-2.01599451166439066346e-03, +-2.01557292214997766863e-03, +-2.01400037965709585719e-03, +-2.01127871827083996512e-03, +-2.00741042708658728663e-03, +-2.00239864825537024207e-03, +-1.99624717465765773305e-03, +-1.98896044720722623214e-03, +-1.98054355178687831532e-03, +-1.97100221581815275573e-03, +-1.96034280446718981242e-03, +-1.94857231648931650270e-03, +-1.93569837971491794798e-03, +-1.92172924617953493238e-03, +-1.90667378690126333891e-03, +-1.89054148630866990580e-03, +-1.87334243632268355843e-03, +-1.85508733009632424509e-03, +-1.83578745541577732087e-03, +-1.81545468776724309642e-03, +-1.79410148307337815980e-03, +-1.77174087010420694757e-03, +-1.74838644256665020488e-03, +-1.72405235087792502863e-03, +-1.69875329362731528234e-03, +-1.67250450873173686292e-03, +-1.64532176429031608451e-03, +-1.61722134914345358134e-03, +-1.58822006314201439985e-03, +-1.55833520713242958296e-03, +-1.52758457266367842983e-03, +-1.49598643142224508110e-03, +-1.46355952440134539153e-03, +-1.43032305081079724740e-03, +-1.39629665673392786875e-03, +-1.36150042353874842389e-03, +-1.32595485604938292078e-03, +-1.28968087048560815441e-03, +-1.25269978217663175389e-03, +-1.21503329305731573931e-03, +-1.17670347895322481742e-03, +-1.13773277666287834717e-03, +-1.09814397084380963379e-03, +-1.05796018071076876506e-03, +-1.01720484655352786697e-03, +-9.75901716082224163044e-04, +-9.34074830608162560291e-04, +-8.91748511068093702332e-04, +-8.48947343900121774093e-04, +-8.05696166779400137388e-04, +-7.62020054221886175734e-04, +-7.17944303064517799773e-04, +-6.73494417830223287419e-04, +-6.28696095985875375196e-04, +-5.83575213102809943477e-04, +-5.38157807926610857671e-04, +-4.92470067366625467893e-04, +-4.46538311412741039091e-04, +-4.00388977988523500975e-04, +-3.54048607749048280420e-04, +-3.07543828832976284295e-04, +-2.60901341576534541618e-04, +-2.14147903198978289919e-04, +-1.67310312467942520764e-04, +-1.20415394353891940199e-04, +-7.34899846812865148926e-05, +-2.65609147871840793706e-05, + 2.03450038059074316498e-05, + 6.72009946930133205637e-05, + 1.13980331857172184195e-04, + 1.60656354898604009258e-04, + 2.07202484214283008147e-04, + 2.53592236118117483629e-04, + 2.99799237895086720992e-04, + 3.45797242778839468078e-04, + 3.91560144845429106229e-04, + 4.37061993814294241171e-04, + 4.82277009748485958104e-04, + 5.27179597645008367682e-04, + 5.71744361908107438623e-04, + 6.15946120696525068264e-04, + 6.59759920136990252182e-04, + 7.03161048395523806745e-04, + 7.46125049599718473056e-04, + 7.88627737602340720367e-04, + 8.30645209580345455537e-04, + 8.72153859460560415377e-04, + 9.13130391164877785494e-04, + 9.53551831667496553602e-04, + 9.93395543856891161116e-04, + 1.03263923919528978652e-03, + 1.07126099016866677127e-03, + 1.10923924252022128127e-03, + 1.14655282726058328768e-03, + 1.18318097244805918271e-03, + 1.21910331473228323099e-03, + 1.25429991065521308224e-03, + 1.28875124770248187904e-03, + 1.32243825509993726680e-03, + 1.35534231434853292934e-03, + 1.38744526949258163359e-03, + 1.41872943711487042515e-03, + 1.44917761605398002535e-03, + 1.47877309683764539099e-03, + 1.50749967082781347223e-03, + 1.53534163907186548513e-03, + 1.56228382085535594075e-03, + 1.58831156195163563510e-03, + 1.61341074256387195449e-03, + 1.63756778495518346382e-03, + 1.66076966076276837624e-03, + 1.68300389799214892943e-03, + 1.70425858768773869599e-03, + 1.72452239027620483382e-03, + 1.74378454157939760671e-03, + 1.76203485849330421936e-03, + 1.77926374433060529266e-03, + 1.79546219382350027462e-03, + 1.81062179778474288683e-03, + 1.82473474742401477189e-03, + 1.83779383831785469647e-03, + 1.84979247403080490283e-03, + 1.86072466938634346195e-03, + 1.87058505338575297924e-03, + 1.87936887177368445838e-03, + 1.88707198924914281921e-03, + 1.89369089132102150393e-03, + 1.89922268580736391258e-03, + 1.90366510397775167036e-03, + 1.90701650133855821721e-03, + 1.90927585806080512588e-03, + 1.91044277905074734968e-03, + 1.91051749366339122978e-03, + 1.90950085505942339544e-03, + 1.90739433920622124437e-03, + 1.90420004352378135701e-03, + 1.89992068517663812051e-03, + 1.89455959901305625789e-03, + 1.88812073515295573110e-03, + 1.88060865622618881600e-03, + 1.87202853426315300560e-03, + 1.86238614723965899625e-03, + 1.85168787527840192179e-03, + 1.83994069650947789270e-03, + 1.82715218259254900957e-03, + 1.81333049390355882657e-03, + 1.79848437438895314942e-03, + 1.78262314609068240993e-03, + 1.76575670334532712838e-03, + 1.74789550666099805648e-03, + 1.72905057627572287561e-03, + 1.70923348540114126287e-03, + 1.68845635315613591676e-03, + 1.66673183719381174349e-03, + 1.64407312602717807851e-03, + 1.62049393105762528852e-03, + 1.59600847831119999759e-03, + 1.57063149988747046033e-03, + 1.54437822512650262292e-03, + 1.51726437149865382714e-03, + 1.48930613522309045725e-03, + 1.46052018162035729919e-03, + 1.43092363520500552576e-03, + 1.40053406952348629723e-03, + 1.36936949674445118327e-03, + 1.33744835700646668569e-03, + 1.30478950753013271321e-03, + 1.27141221150076761358e-03, + 1.23733612672830939165e-03, + 1.20258129409077482892e-03, + 1.16716812576892663492e-03, + 1.13111739327765117337e-03, + 1.09445021530241268400e-03, + 1.05718804534711313843e-03, + 1.01935265920083785798e-03, + 9.80966142230535508365e-04, + 9.42050876507689177730e-04, + 9.02629527775573197758e-04, + 8.62725032265359496712e-04, + 8.22360583368397595437e-04, + 7.81559618172762574431e-04, + 7.40345803871171343619e-04, + 6.98743024048840326648e-04, + 6.56775364859214197573e-04, + 6.14467101094864410517e-04, + 5.71842682162310611722e-04, + 5.28926717968548746641e-04, + 4.85743964727467576921e-04, + 4.42319310694356789340e-04, + 3.98677761836690037860e-04, + 3.54844427449443563551e-04, + 3.10844505723203393555e-04, + 2.66703269273363180372e-04, + 2.22446050638747323033e-04, + 1.78098227757677587350e-04, + 1.33685209430572742549e-04, + 8.92324207763590298084e-05, + 4.47652886917426873583e-05, + 3.09227321650505732558e-07, +-4.41103764515531808835e-05, +-8.84681774910541152872e-05, +-1.32738886852529214266e-04, +-1.76897286187552060842e-04, +-2.20918242094528819363e-04, +-2.64776720409321865164e-04, +-3.08447800427395421845e-04, +-3.51906689049402091746e-04, +-3.95128734842202674043e-04, +-4.38089442007342469865e-04, +-4.80764484249080186352e-04, +-5.23129718534129112967e-04, +-5.65161198735287346670e-04, +-6.06835189151545676724e-04, +-6.48128177896318104570e-04, +-6.89016890147269131690e-04, +-7.29478301249281038503e-04, +-7.69489649664180678720e-04, +-8.09028449758908115366e-04, +-8.48072504425961999630e-04, +-8.86599917528026388626e-04, +-9.24589106160850367731e-04, +-9.62018812726749862618e-04, +-9.98868116812330619769e-04, +-1.03511644686372960081e-03, +-1.07074359165286784289e-03, +-1.10572971152834206160e-03, +-1.14005534944471237715e-03, +-1.17370144176403299122e-03, +-1.20664932882368503703e-03, +-1.23888076526462546922e-03, +-1.27037793011433868158e-03, +-1.30112343661913792969e-03, +-1.33110034181987751598e-03, +-1.36029215586637268476e-03, +-1.38868285106535536630e-03, +-1.41625687065657750174e-03, +-1.44299913731265943770e-03, +-1.46889506135814513696e-03, +-1.49393054870271117275e-03, +-1.51809200848501517356e-03, +-1.54136636042246982434e-03, +-1.56374104186323185060e-03, +-1.58520401453656292236e-03, +-1.60574377099796661295e-03, +-1.62534934076566579299e-03, +-1.64401029614518693484e-03, +-1.66171675773892622320e-03, +-1.67845939963788895466e-03, +-1.69422945429279826236e-03, +-1.70901871706225839433e-03, +-1.72281955043516879847e-03, +-1.73562488792599364622e-03, +-1.74742823764018669758e-03, +-1.75822368550844964838e-03, +-1.76800589818810072879e-03, +-1.77677012563024231892e-03, +-1.78451220331139900031e-03, +-1.79122855412879207482e-03, +-1.79691618995835998736e-03, +-1.80157271287491316247e-03, +-1.80519631603399109167e-03, +-1.80778578421531151664e-03, +-1.80934049402758445960e-03, +-1.80986041377503045595e-03, +-1.80934610298588618299e-03, +-1.80779871160341876896e-03, +-1.80521997884027364349e-03, +-1.80161223169698209157e-03, +-1.79697838314586038136e-03, +-1.79132192998154664808e-03, +-1.78464695033966652855e-03, +-1.77695810088541257706e-03, +-1.76826061367380709712e-03, +-1.75856029268379684440e-03, +-1.74786351002833607871e-03, +-1.73617720184306720613e-03, +-1.72350886385598295499e-03, +-1.70986654664103516175e-03, +-1.69525885055866825345e-03, +-1.67969492038625377826e-03, +-1.66318443964190258721e-03, +-1.64573762460525812104e-03, +-1.62736521803862185451e-03, +-1.60807848261251156753e-03, +-1.58788919403957031612e-03, +-1.56680963392096320175e-03, +-1.54485258230964710331e-03, +-1.52203130999494277119e-03, +-1.49835957051309000103e-03, +-1.47385159188855594317e-03, +-1.44852206811105200211e-03, +-1.42238615035335702781e-03, +-1.39545943793505230687e-03, +-1.36775796903791223985e-03, +-1.33929821117795126197e-03, +-1.31009705144011874209e-03, +-1.28017178648149091390e-03, +-1.24954011230838865631e-03, +-1.21822011383393023938e-03, +-1.18623025422220701106e-03, +-1.15358936402481875548e-03, +-1.12031663011664538339e-03, +-1.08643158443716956497e-03, +-1.05195409254393249660e-03, +-1.01690434198485049264e-03, +-9.81302830496187097550e-04, +-9.45170354033052825121e-04, +-9.08527994639429640512e-04, +-8.71397108164778015985e-04, +-8.33799311834413085960e-04, +-7.95756471680627718197e-04, +-7.57290689842498644137e-04, +-7.18424291740831638675e-04, +-6.79179813136611995432e-04, +-6.39579987079505734443e-04, +-5.99647730754900086352e-04, +-5.59406132236475598166e-04, +-5.18878437151933970262e-04, +-4.78088035270234697639e-04, +-4.37058447017129952060e-04, +-3.95813309927481478661e-04, +-3.54376365041849988782e-04, +-3.12771443255252100824e-04, +-2.71022451625898674193e-04, +-2.29153359651793514821e-04, +-1.87188185523051535668e-04, +-1.45150982357815703074e-04, +-1.03065824429653753224e-04, +-6.09567933943611181980e-05, +-1.88479645237432815287e-05, + 2.32366070450612883841e-05, + 6.52729000375716606440e-05, + 1.07236940739442618243e-04, + 1.49104816654926491124e-04, + 1.90852690119197040226e-04, + 2.32456811856789096653e-04, + 2.73893534477760703088e-04, + 3.15139325904901243872e-04, + 3.56170782723636393866e-04, + 3.96964643447348004834e-04, + 4.37497801690561933553e-04, + 4.77747319242539513363e-04, + 5.17690439033898983090e-04, + 5.57304597988927475152e-04, + 5.96567439756349820155e-04, + 6.35456827311364227072e-04, + 6.73950855421827322786e-04, + 7.12027862971859829694e-04, + 7.49666445135031877037e-04, + 7.86845465391861000233e-04, + 8.23544067383306889127e-04, + 8.59741686594572016369e-04, + 8.95418061862311427494e-04, + 9.30553246699131696683e-04, + 9.65127620428410772438e-04, + 9.99121899124090018587e-04, + 1.03251714634870848247e-03, + 1.06529478368399947198e-03, + 1.09743660104794104639e-03, + 1.12892476679308227140e-03, + 1.15974183757998469332e-03, + 1.18987076802038013908e-03, + 1.21929492008520171109e-03, + 1.24799807227183364583e-03, + 1.27596442852571370294e-03, + 1.30317862691138467227e-03, + 1.32962574802824510904e-03, + 1.35529132316640921890e-03, + 1.38016134219821656921e-03, + 1.40422226120109406612e-03, + 1.42746100980768492357e-03, + 1.44986499827917236088e-03, + 1.47142212429823100381e-03, + 1.49212077947745262729e-03, + 1.51194985558042080918e-03, + 1.53089875045162937886e-03, + 1.54895737365219089698e-03, + 1.56611615179862813038e-03, + 1.58236603360162059878e-03, + 1.59769849460209630194e-03, + 1.61210554160250824594e-03, + 1.62557971679072794415e-03, + 1.63811410155455141995e-03, + 1.64970231998493792151e-03, + 1.66033854206613972274e-03, + 1.67001748655128297305e-03, + 1.67873442352191011920e-03, + 1.68648517663034331823e-03, + 1.69326612502385489591e-03, + 1.69907420494976057514e-03, + 1.70390691104087862832e-03, + 1.70776229728072394785e-03, + 1.71063897764836807952e-03, + 1.71253612644269893883e-03, + 1.71345347828618104098e-03, + 1.71339132780851089409e-03, + 1.71235052901041605485e-03, + 1.71033249430839581935e-03, + 1.70733919326115121499e-03, + 1.70337315097866446277e-03, + 1.69843744621518731933e-03, + 1.69253570914738513120e-03, + 1.68567211883928003494e-03, + 1.67785140039562329257e-03, + 1.66907882180561645095e-03, + 1.65936019047902743109e-03, + 1.64870184947697967330e-03, + 1.63711067343976380412e-03, + 1.62459406421430947211e-03, + 1.61115994618396237217e-03, + 1.59681676130369741735e-03, + 1.58157346384365333700e-03, + 1.56543951484419598813e-03, + 1.54842487628618539174e-03, + 1.53054000497979212497e-03, + 1.51179584617556041562e-03, + 1.49220382690190903063e-03, + 1.47177584903268165312e-03, + 1.45052428208925355928e-03, + 1.42846195578139154199e-03, + 1.40560215229139080610e-03, + 1.38195859830608975584e-03, + 1.35754545680155853417e-03, + 1.33237731858531225151e-03, + 1.30646919360115246027e-03, + 1.27983650200173999789e-03, + 1.25249506499428768340e-03, + 1.22446109546453757271e-03, + 1.19575118838507522302e-03, + 1.16638231101316865689e-03, + 1.13637179288388632040e-03, + 1.10573731560490210422e-03, + 1.07449690245847175561e-03, + 1.04266890781677537894e-03, + 1.01027200637724160967e-03, + 9.77325182223491746580e-04, + 9.43847717718836014267e-04, + 9.09859182238561756129e-04, + 8.75379420747673811856e-04, + 8.40428542230697460044e-04, + 8.05026907980306420144e-04, + 7.69195119751593810696e-04, + 7.32954007788833667922e-04, + 6.96324618731728513937e-04, + 6.59328203408161448926e-04, + 6.21986204520240414974e-04, + 5.84320244231672147536e-04, + 5.46352111662109520517e-04, + 5.08103750297240336353e-04, + 4.69597245320941603965e-04, + 4.30854810877143471967e-04, + 3.91898777268710394022e-04, + 3.52751578100453573074e-04, + 3.13435737374358550089e-04, + 2.73973856543509894194e-04, + 2.34388601532805235282e-04, + 1.94702689733898895181e-04, + 1.54938876981224293557e-04, + 1.15119944517208389599e-04, + 7.52686859541390425104e-05, + 3.54078942394808599795e-05, +-4.43965136725644293991e-06, +-4.42511982989445055948e-05, +-8.40040336590952227153e-05, +-1.23675497166556415483e-04, +-1.63242994059274422816e-04, +-2.02684007949782501144e-04, +-2.41976113625108971150e-04, +-2.81096989783838162574e-04, +-3.20024431703046653274e-04, +-3.58736363828217243860e-04, +-3.97210852278301535575e-04, +-4.35426117259783847756e-04, +-4.73360545382079051305e-04, +-5.10992701867309432294e-04, +-5.48301342648169556804e-04, +-5.85265426346414513459e-04, +-6.21864126125226549316e-04, +-6.58076841409443590199e-04, +-6.93883209466395465582e-04, +-7.29263116841149562630e-04, +-7.64196710639690078223e-04, +-7.98664409653720487083e-04, +-8.32646915320844871987e-04, +-8.66125222514040646153e-04, +-8.99080630154340944109e-04, +-9.31494751640883481870e-04, +-9.63349525092406142567e-04, +-9.94627223394778684981e-04, +-1.02531046404839951310e-03, +-1.05538221881074458820e-03, +-1.08482582312822528441e-03, +-1.11362498535213291090e-03, +-1.14176379573408177427e-03, +-1.16922673519527877718e-03, +-1.19599868386546836010e-03, +-1.22206492938624691758e-03, +-1.24741117497479086888e-03, +-1.27202354724320165595e-03, +-1.29588860376930693416e-03, +-1.31899334041485176428e-03, +-1.34132519838702510620e-03, +-1.36287207103959304329e-03, +-1.38362231040987894090e-03, +-1.40356473348816814667e-03, +-1.42268862821608036220e-03, +-1.44098375921079607451e-03, +-1.45844037321212166396e-03, +-1.47504920424929150333e-03, +-1.49080147852505740143e-03, +-1.50568891901449236279e-03, +-1.51970374977587058263e-03, +-1.53283869997163850300e-03, +-1.54508700759743169105e-03, +-1.55644242291698388023e-03, +-1.56689921160158636589e-03, +-1.57645215757227954816e-03, +-1.58509656554349596252e-03, +-1.59282826326696629569e-03, +-1.59964360347482673595e-03, +-1.60553946552108848557e-03, +-1.61051325672077034167e-03, +-1.61456291338620840613e-03, +-1.61768690156018470419e-03, +-1.61988421744570839506e-03, +-1.62115438753249706261e-03, +-1.62149746842027214430e-03, +-1.62091404633929480651e-03, +-1.61940523636864598667e-03, +-1.61697268135293863688e-03, +-1.61361855051833538548e-03, +-1.60934553778894714506e-03, +-1.60415685980480290408e-03, +-1.59805625364277783043e-03, +-1.59104797424202554224e-03, +-1.58313679153566032841e-03, +-1.57432798729054113616e-03, +-1.56462735165729103538e-03, +-1.55404117943255706651e-03, +-1.54257626603623507200e-03, +-1.53023990320586564598e-03, +-1.51703987441107932509e-03, +-1.50298444999091796934e-03, +-1.48808238201701193738e-03, +-1.47234289888582359565e-03, +-1.45577569964323665606e-03, +-1.43839094804500198903e-03, +-1.42019926635660867151e-03, +-1.40121172889639514399e-03, +-1.38143985532579059369e-03, +-1.36089560369062070010e-03, +-1.33959136321799648049e-03, +-1.31753994687265748795e-03, +-1.29475458367754288694e-03, +-1.27124891080319826590e-03, +-1.24703696543038513624e-03, +-1.22213317639110834699e-03, +-1.19655235559304484218e-03, +-1.17030968923203648052e-03, +-1.14342072879827219220e-03, +-1.11590138188130184350e-03, +-1.08776790277930086870e-03, +-1.05903688291816215454e-03, +-1.02972524108603069419e-03, +-9.99850213489021427335e-04, +-9.69429343633939504844e-04, +-9.38480472043964680448e-04, +-9.07021725813329186133e-04, +-8.75071508006883031112e-04, +-8.42648486911279294594e-04, +-8.09771585143337466368e-04, +-7.76459968622407611070e-04, +-7.42733035413201104179e-04, +-7.08610404445038041289e-04, +-6.74111904114616314332e-04, +-6.39257560778936587825e-04, +-6.04067587144468801964e-04, +-5.68562370559859918927e-04, +-5.32762461218706014771e-04, +-4.96688560279258763987e-04, +-4.60361507907912782377e-04, +-4.23802271253376780860e-04, +-3.87031932358470730920e-04, +-3.50071676016493139785e-04, +-3.12942777579159074532e-04, +-2.75666590723110279098e-04, +-2.38264535182076194354e-04, +-2.00758084451451004676e-04, +-1.63168753473010485957e-04, +-1.25518086305888461329e-04, +-8.78276437918047763126e-05, +-5.01189912206633324926e-05, +-1.24136860045527507159e-05, + 2.52667346337536352944e-05, + 6.29007659498319457100e-05, + 1.00466947938114190518e-04, + 1.37943877556209900086e-04, + 1.75310220906359231921e-04, + 2.12544725367042178004e-04, + 2.49626231667856310695e-04, + 2.86533685900810760391e-04, + 3.23246151461219666419e-04, + 3.59742820911436455861e-04, + 3.96003027760712372068e-04, + 4.32006258154472920323e-04, + 4.67732162466665663501e-04, + 5.03160566788037619604e-04, + 5.38271484304469029561e-04, + 5.73045126558938025356e-04, + 6.07461914590199476491e-04, + 6.41502489942463185145e-04, + 6.75147725539870118862e-04, + 7.08378736419115317274e-04, + 7.41176890315008965633e-04, + 7.73523818092431607665e-04, + 8.05401424019106036527e-04, + 8.36791895873423112462e-04, + 8.67677714881635517297e-04, + 8.98041665478958536263e-04, + 9.27866844889067626453e-04, + 9.57136672516743498666e-04, + 9.85834899148405139485e-04, + 1.01394561595543404760e-03, + 1.04145326329548363296e-03, + 1.06834263930647441546e-03, + 1.09459890828899372543e-03, + 1.12020760887248218077e-03, + 1.14515466196026915839e-03, + 1.16942637844957234711e-03, + 1.19300946672199316770e-03, + 1.21589103990064808375e-03, + 1.23805862286953697812e-03, + 1.25950015905194477768e-03, + 1.28020401694373142133e-03, + 1.30015899639822005152e-03, + 1.31935433465907368637e-03, + 1.33777971213847393650e-03, + 1.35542525793661992536e-03, + 1.37228155510049436815e-03, + 1.38833964561861015856e-03, + 1.40359103514923078820e-03, + 1.41802769747961950574e-03, + 1.43164207871396926761e-03, + 1.44442710118785071390e-03, + 1.45637616710717282889e-03, + 1.46748316190982897207e-03, + 1.47774245734831524007e-03, + 1.48714891429181411860e-03, + 1.49569788524642525128e-03, + 1.50338521659217202661e-03, + 1.51020725053600747730e-03, + 1.51616082677973940986e-03, + 1.52124328390220494439e-03, + 1.52545246045525904888e-03, + 1.52878669577304190583e-03, + 1.53124483049437549141e-03, + 1.53282620679826551459e-03, + 1.53353066835256834737e-03, + 1.53335855997613302801e-03, + 1.53231072701479021855e-03, + 1.53038851443190564161e-03, + 1.52759376561413247157e-03, + 1.52392882089336643460e-03, + 1.51939651578598348275e-03, + 1.51400017895056589190e-03, + 1.50774362986558999739e-03, + 1.50063117622853013297e-03, + 1.49266761107828566796e-03, + 1.48385820964260146428e-03, + 1.47420872591265969889e-03, + 1.46372538894702294843e-03, + 1.45241489890715028306e-03, + 1.44028442282717193852e-03, + 1.42734159012037307990e-03, + 1.41359448782537428478e-03, + 1.39905165559475546354e-03, + 1.38372208042934524870e-03, + 1.36761519116132632817e-03, + 1.35074085268957954850e-03, + 1.33310935997071780372e-03, + 1.31473143176951009180e-03, + 1.29561820417240587851e-03, + 1.27578122386814139279e-03, + 1.25523244119940383980e-03, + 1.23398420298978994322e-03, + 1.21204924515017141255e-03, + 1.18944068506927815715e-03, + 1.16617201379247414916e-03, + 1.14225708799397369063e-03, + 1.11771012174662520873e-03, + 1.09254567809480241866e-03, + 1.06677866043477544145e-03, + 1.04042430370825892544e-03, + 1.01349816541371835939e-03, + 9.86016116441160682393e-04, + 9.57994331735642526242e-04, + 9.29449280794978792072e-04, + 9.00397718007248429838e-04, + 8.70856672833736898155e-04, + 8.40843439843083260109e-04, + 8.10375568602425999827e-04, + 7.79470853431471315254e-04, + 7.48147323025479091436e-04, + 7.16423229952991972615e-04, + 6.84317040034933634675e-04, + 6.51847421610750755311e-04, + 6.19033234697776140604e-04, + 5.85893520050684464551e-04, + 5.52447488126856715678e-04, + 5.18714507964034747881e-04, + 4.84714095977265707355e-04, + 4.50465904680799719868e-04, + 4.15989711342059980889e-04, + 3.81305406573980180604e-04, + 3.46432982872289069957e-04, + 3.11392523104614979499e-04, + 2.76204188957184101297e-04, + 2.40888209347176124927e-04, + 2.05464868805964193327e-04, + 1.69954495840752130374e-04, + 1.34377451281002371951e-04, + 9.87541166164100474301e-05, + 6.31048823327933465369e-05, + 2.74501362534655310964e-05, +-8.18974810873998083655e-06, +-4.37944231806596304514e-05, +-7.93435789334627901382e-05, +-1.14816954455838874283e-04, +-1.50194349489415440680e-04, +-1.85455635919215376531e-04, +-2.20580769213464333118e-04, +-2.55549799805626501933e-04, +-2.90342884412502183315e-04, +-3.24940297281641648271e-04, +-3.59322441362583172488e-04, +-3.93469859394135197499e-04, +-4.27363244902898627587e-04, +-4.60983453105939474694e-04, +-4.94311511711763339541e-04, +-5.27328631613451729448e-04, +-5.60016217467949450198e-04, +-5.92355878155555572520e-04, +-6.24329437113732110647e-04, +-6.55918942539445706461e-04, +-6.87106677454311985491e-04, +-7.17875169626881314694e-04, +-7.48207201346719435846e-04, +-7.78085819044304792189e-04, +-8.07494342752076792701e-04, +-8.36416375400828135574e-04, +-8.64835811946538645517e-04, +-8.92736848322267452678e-04, +-9.20103990210890628799e-04, +-9.46922061632605917975e-04, +-9.73176213343664533485e-04, +-9.98851931040956823177e-04, +-1.02393504336819934561e-03, +-1.04841172971923139896e-03, +-1.07226852783420443203e-03, +-1.09549234118443920144e-03, +-1.11807044614193923544e-03, +-1.13999049892964587558e-03, +-1.16124054234865384944e-03, +-1.18180901227872168710e-03, +-1.20168474394853771157e-03, +-1.22085697797251154818e-03, +-1.23931536615045907561e-03, +-1.25704997702758545543e-03, +-1.27405130121131457410e-03, +-1.29031025644257271376e-03, +-1.30581819241839158958e-03, +-1.32056689536371330701e-03, +-1.33454859234959002240e-03, +-1.34775595535592540575e-03, +-1.36018210507637331112e-03, +-1.37182061446355658269e-03, +-1.38266551201276610521e-03, +-1.39271128478253266095e-03, +-1.40195288115051316068e-03, +-1.41038571330337893055e-03, +-1.41800565945951256505e-03, +-1.42480906582346297101e-03, +-1.43079274827126803893e-03, +-1.43595399376592503145e-03, +-1.44029056150241801561e-03, +-1.44380068378189055887e-03, +-1.44648306661469805943e-03, +-1.44833689005223324210e-03, +-1.44936180824753674604e-03, +-1.44955794924493913504e-03, +-1.44892591449903443759e-03, +-1.44746677812355745846e-03, +-1.44518208587075661954e-03, +-1.44207385384213272739e-03, +-1.43814456693148930849e-03, +-1.43339717700140213338e-03, +-1.42783510079440463525e-03, +-1.42146221758030649220e-03, +-1.41428286654118624127e-03, +-1.40630184389584447259e-03, +-1.39752439976549721300e-03, +-1.38795623478277815703e-03, +-1.37760349644625219347e-03, +-1.36647277522266587767e-03, +-1.35457110039932790077e-03, +-1.34190593568940877423e-03, +-1.32848517459267919869e-03, +-1.31431713551467539529e-03, +-1.29941055664714501944e-03, +-1.28377459061317523298e-03, +-1.26741879887994307423e-03, +-1.25035314594268138870e-03, +-1.23258799328333345374e-03, +-1.21413409310764655244e-03, +-1.19500258186405750038e-03, +-1.17520497354900595698e-03, +-1.15475315280194222242e-03, +-1.13365936779458078426e-03, +-1.11193622291853085743e-03, +-1.08959667127568366092e-03, +-1.06665400697560715411e-03, +-1.04312185724514980105e-03, +-1.01901417435390105257e-03, +-9.94345227361283657413e-04, +-9.69129593689562135808e-04, +-9.43382150527953696438e-04, +-9.17118066072678981768e-04, +-8.90352790608596130796e-04, +-8.63102047436990239826e-04, +-8.35381823655337134304e-04, +-8.07208360794198893050e-04, +-7.78598145316998046898e-04, +-7.49567898987517377586e-04, +-7.20134569111909820377e-04, +-6.90315318659743713467e-04, +-6.60127516270525181372e-04, +-6.29588726151278908240e-04, +-5.98716697871097070296e-04, +-5.67529356058555788274e-04, +-5.36044790008002544103e-04, +-5.04281243200707597792e-04, +-4.72257102746954785574e-04, +-4.39990888755171366542e-04, +-4.07501243634276436468e-04, +-3.74806921335187493566e-04, +-3.41926776538259847692e-04, +-3.08879753792126179272e-04, +-2.75684876610755174881e-04, +-2.42361236534725988821e-04, +-2.08927982163283266397e-04, +-1.75404308162909107092e-04, +-1.41809444259267161117e-04, +-1.08162644218829444537e-04, +-7.44831748259327543465e-05, +-4.07903048621291604812e-05, +-7.10329409388432176530e-06, + 2.65586177250463047000e-05, + 6.01762218302914552804e-05, + 9.37303513963725428056e-05, + 1.27201892452491753700e-04, + 1.60571794759468988462e-04, + 1.93821082639647593359e-04, + 2.26930865755815396869e-04, + 2.59882349831586946780e-04, + 2.92656847307690018770e-04, + 3.25235787928080961190e-04, + 3.57600729249660839303e-04, + 3.89733367070243196494e-04, + 4.21615545768098812836e-04, + 4.53229268547830762767e-04, + 4.84556707586572316029e-04, + 5.15580214074757778309e-04, + 5.46282328146297608759e-04, + 5.76645788691256379679e-04, + 6.06653543047546025234e-04, + 6.36288756564360792091e-04, + 6.65534822032997838703e-04, + 6.94375368979479354152e-04, + 7.22794272813854533910e-04, + 7.50775663831016056536e-04, + 7.78303936058092520403e-04, + 8.05363755943419535807e-04, + 8.31940070882321368144e-04, + 8.58018117574883202973e-04, + 8.83583430211330928851e-04, + 9.08621848479962369513e-04, + 9.33119525393878300641e-04, + 9.57062934931689960998e-04, + 9.80438879488230432754e-04, + 1.00323449713107977488e-03, + 1.02543726865899926387e-03, + 1.04703502445835567626e-03, + 1.06801595115381007736e-03, + 1.08836859804968565969e-03, + 1.10808188335835252139e-03, + 1.12714510021262159095e-03, + 1.14554792245836578428e-03, + 1.16328041022489597940e-03, + 1.18033301526926739412e-03, + 1.19669658609257542788e-03, + 1.21236237282488557888e-03, + 1.22732203187633261143e-03, + 1.24156763035219172911e-03, + 1.25509165022920821282e-03, + 1.26788699229131874430e-03, + 1.27994697982256044888e-03, + 1.29126536205536050946e-03, + 1.30183631737235691941e-03, + 1.31165445626020235083e-03, + 1.32071482401390893208e-03, + 1.32901290319023448333e-03, + 1.33654461580914787205e-03, + 1.34330632530221187430e-03, + 1.34929483820697367936e-03, + 1.35450740560668671242e-03, + 1.35894172431470653187e-03, + 1.36259593780313340884e-03, + 1.36546863687537654505e-03, + 1.36755886008250635531e-03, + 1.36886609388332716047e-03, + 1.36939027254837260295e-03, + 1.36913177780802522952e-03, + 1.36809143824524986725e-03, + 1.36627052843346185988e-03, + 1.36367076782027457811e-03, + 1.36029431935798012128e-03, + 1.35614378788172988514e-03, + 1.35122221823664079472e-03, + 1.34553309315501787302e-03, + 1.33908033088521731709e-03, + 1.33186828257363392043e-03, + 1.32390172940159678815e-03, + 1.31518587947901410308e-03, + 1.30572636449661312261e-03, + 1.29552923613923372595e-03, + 1.28460096226200824743e-03, + 1.27294842283218667331e-03, + 1.26057890563882179363e-03, + 1.24750010177327374725e-03, + 1.23372010088306036796e-03, + 1.21924738620211555243e-03, + 1.20409082936042593007e-03, + 1.18825968497621972837e-03, + 1.17176358503399751995e-03, + 1.15461253305178279151e-03, + 1.13681689804116217886e-03, + 1.11838740826359175386e-03, + 1.09933514478704010865e-03, + 1.07967153484642012021e-03, + 1.05940834501207096011e-03, + 1.03855767417023879713e-03, + 1.01713194631976918542e-03, + 9.95143903189260560158e-04, + 9.72606596679090784803e-04, + 9.49533381132751461845e-04, + 9.25937905442090168628e-04, + 9.01834104991060562725e-04, + 8.77236193442972891042e-04, + 8.52158654375306323994e-04, + 8.26616232768399242931e-04, + 8.00623926351481181481e-04, + 7.74196976812098437357e-04, + 7.47350860873750573281e-04, + 7.20101281246932219647e-04, + 6.92464157459100611118e-04, + 6.64455616568401037821e-04, + 6.36091983767215129672e-04, + 6.07389772880511497576e-04, + 5.78365676764722234753e-04, + 5.49036557612754723412e-04, + 5.19419437170334677249e-04, + 4.89531486870367453512e-04, + 4.59390017889853828105e-04, + 4.29012471135610442413e-04, + 3.98416407164879030761e-04, + 3.67619496046182284588e-04, + 3.36639507166480267224e-04, + 3.05494298990473505794e-04, + 2.74201808777935912304e-04, + 2.42780042265004216643e-04, + 2.11247063315343980641e-04, + 1.79620983547136846585e-04, + 1.47919951941878261405e-04, + 1.16162144440711673481e-04, + 8.43657535348246083538e-05, + 5.25489778551051491483e-05, + 2.07300117675779430298e-05, +-1.10729650196668325771e-05, +-4.28417978320822792019e-05, +-7.45583673808965783410e-05, +-1.06204600086071425293e-04, +-1.37762478364149087246e-04, +-1.69214050874914927148e-04, +-2.00541442721614891851e-04, +-2.31726865598118244574e-04, +-2.62752627878274269604e-04, +-2.93601144640412165671e-04, +-3.24254947622835021804e-04, +-3.54696695103594577137e-04, +-3.84909181699200184275e-04, +-4.14875348077196936039e-04, +-4.44578290576414924141e-04, +-4.74001270730014352076e-04, +-5.03127724685752076780e-04, +-5.31941272518206861690e-04, +-5.60425727427743720910e-04, +-5.88565104821016545078e-04, +-6.16343631268131183359e-04, +-6.43745753330938032602e-04, +-6.70756146258231328826e-04, +-6.97359722542432612299e-04, +-7.23541640333268576586e-04, +-7.49287311703654272145e-04, +-7.74582410763238315282e-04, +-7.99412881615075860547e-04, +-8.23764946151039185139e-04, +-8.47625111681623221935e-04, +-8.70980178395970995424e-04, +-8.93817246647941095888e-04, +-9.16123724064377706680e-04, +-9.37887332471280203011e-04, +-9.59096114634606271634e-04, +-9.79738440811607448275e-04, +-9.99803015109290834847e-04, +-1.01927888164651272128e-03, +-1.03815543051633853155e-03, +-1.05642240354548912901e-03, +-1.07406989984759745557e-03, +-1.09108838116762723279e-03, +-1.10746867701414018585e-03, +-1.12320198957698577993e-03, +-1.13827989842765417428e-03, +-1.15269436499997502028e-03, +-1.16643773684832734866e-03, +-1.17950275168172556868e-03, +-1.19188254117136706138e-03, +-1.20357063452954798910e-03, +-1.21456096185834725582e-03, +-1.22484785726622159678e-03, +-1.23442606175099434812e-03, +-1.24329072584775926144e-03, +-1.25143741204040113979e-03, +-1.25886209693559965317e-03, +-1.26556117319820459269e-03, +-1.27153145124719456523e-03, +-1.27677016071131685555e-03, +-1.28127495164393639428e-03, +-1.28504389549651746975e-03, +-1.28807548585040771913e-03, +-1.29036863890675851559e-03, +-1.29192269373445381593e-03, +-1.29273741227616803182e-03, +-1.29281297911274461153e-03, +-1.29215000098622341193e-03, +-1.29074950608205050485e-03, +-1.28861294307102769788e-03, +-1.28574217991181470426e-03, +-1.28213950241485154062e-03, +-1.27780761256874805798e-03, +-1.27274962663027619951e-03, +-1.26696907297930137261e-03, +-1.26046988974006066338e-03, +-1.25325642217039056117e-03, +-1.24533341982049493464e-03, +-1.23670603346324884178e-03, +-1.22737981179783643172e-03, +-1.21736069792890478670e-03, +-1.20665502562341490217e-03, +-1.19526951534740743209e-03, +-1.18321127008547502014e-03, +-1.17048777094514431553e-03, +-1.15710687254899267061e-03, +-1.14307679821747196908e-03, +-1.12840613494519497600e-03, +-1.11310382817380736260e-03, +-1.09717917636461301072e-03, +-1.08064182537422016558e-03, +-1.06350176263660047178e-03, +-1.04576931115505939590e-03, +-1.02745512330771390092e-03, +-1.00857017447020984660e-03, +-9.89125756459348273036e-04, +-9.69133470801857087144e-04, +-9.48605221831876478482e-04, +-9.27553209621573911299e-04, +-9.05989922748946536341e-04, +-8.83928130907113245029e-04, +-8.61380877359472856523e-04, +-8.38361471245136369995e-04, +-8.14883479739194086997e-04, +-7.90960720072537894904e-04, +-7.66607251415539741463e-04, +-7.41837366630958413780e-04, +-7.16665583900111865384e-04, +-6.91106638228288503237e-04, +-6.65175472833141076361e-04, +-6.38887230421945938666e-04, +-6.12257244362626436643e-04, +-5.85301029753312320944e-04, +-5.58034274396206606862e-04, +-5.30472829680567778236e-04, +-5.02632701380270412693e-04, +-4.74530040371252698900e-04, +-4.46181133274236403283e-04, +-4.17602393028139700758e-04, +-3.88810349399469656114e-04, +-3.59821639433645487551e-04, +-3.30652997853107073409e-04, +-3.01321247408244021881e-04, +-2.71843289186502834551e-04, +-2.42236092885274642951e-04, +-2.12516687054165319707e-04, +-1.82702149312243965380e-04, +-1.52809596545888838484e-04, +-1.22856175092848034355e-04, +-9.28590509181383036126e-05, +-6.28353997874044387486e-05, +-3.28023974433953014970e-05, +-2.77720979095154411141e-06, + 2.72230169033535440140e-05, + 5.71811657920477271538e-05, + 8.70801592019578094960e-05, + 1.16902968358433966434e-04, + 1.46632623073032026736e-04, + 1.76252221389186882524e-04, + 2.05744939180186014712e-04, + 2.35094039694530468169e-04, + 2.64282883042567088867e-04, + 2.93294935619551385558e-04, + 3.22113779459532194229e-04, + 3.50723121515214011305e-04, + 3.79106802857572401221e-04, + 4.07248807791192634405e-04, + 4.35133272879688717035e-04, + 4.62744495875839806538e-04, + 4.90066944551884237959e-04, + 5.17085265424790572163e-04, + 5.43784292371653644321e-04, + 5.70149055130390425110e-04, + 5.96164787680977456552e-04, + 6.21816936502533586587e-04, + 6.47091168701626482176e-04, + 6.71973380007443560867e-04, + 6.96449702628909074476e-04, + 7.20506512970012593690e-04, + 7.44130439198579488221e-04, + 7.67308368664491478525e-04, + 7.90027455163207908972e-04, + 8.12275126040571966018e-04, + 8.34039089134997737793e-04, + 8.55307339553189088961e-04, + 8.76068166275680644713e-04, + 8.96310158588609247332e-04, + 9.16022212337969966855e-04, + 9.35193536003619163739e-04, + 9.53813656588502287864e-04, + 9.71872425321206783247e-04, + 9.89360023167912576089e-04, + 1.00626696615104373536e-03, + 1.02258411047174220705e-03, + 1.03830265743327931904e-03, + 1.05341415816306632411e-03, + 1.06791051813036243917e-03, + 1.08178400145754450255e-03, + 1.09502723502257035167e-03, + 1.10763321235048616507e-03, + 1.11959529729188916186e-03, + 1.13090722748666861440e-03, + 1.14156311761065294014e-03, + 1.15155746240435427445e-03, + 1.16088513948151006439e-03, + 1.16954141191641532681e-03, + 1.17752193060865497330e-03, + 1.18482273642408174330e-03, + 1.19144026211101582494e-03, + 1.19737133399079663347e-03, + 1.20261317342187467987e-03, + 1.20716339803685892770e-03, + 1.21102002275194891440e-03, + 1.21418146054847906831e-03, + 1.21664652302620073833e-03, + 1.21841442072828740756e-03, + 1.21948476323806070595e-03, + 1.21985755904754564205e-03, + 1.21953321519817120717e-03, + 1.21851253669401512168e-03, + 1.21679672568812116337e-03, + 1.21438738044255738029e-03, + 1.21128649406303441106e-03, + 1.20749645300896710394e-03, + 1.20302003538006298602e-03, + 1.19786040898056927312e-03, + 1.19202112916260414589e-03, + 1.18550613644981912495e-03, + 1.17831975394308238227e-03, + 1.17046668450985027511e-03, + 1.16195200775891173579e-03, + 1.15278117680258848643e-03, + 1.14296001480831705549e-03, + 1.13249471134179986558e-03, + 1.12139181850401392637e-03, + 1.10965824686446259441e-03, + 1.09730126119316579933e-03, + 1.08432847599404177941e-03, + 1.07074785084228674831e-03, + 1.05656768552886740596e-03, + 1.04179661501472100617e-03, + 1.02644360419797825434e-03, + 1.01051794249726128137e-03, + 9.94029238254327297819e-04, + 9.76987412959428496231e-04, + 9.59402695302853094836e-04, + 9.41285615056165433402e-04, + 9.22646996786851249575e-04, + 9.03497953410057892502e-04, + 8.83849879581315145925e-04, + 8.63714444933994722302e-04, + 8.43103587165879497442e-04, + 8.22029504978451252585e-04, + 8.00504650873420757484e-04, + 7.78541723810587853530e-04, + 7.56153661731407702139e-04, + 7.33353633952590140861e-04, + 7.10155033434391397620e-04, + 6.86571468927704795654e-04, + 6.62616757005092820061e-04, + 6.38304913980008450068e-04, + 6.13650147719164789327e-04, + 5.88666849352420377441e-04, + 5.63369584885875388305e-04, + 5.37773086722076747342e-04, + 5.11892245092671863312e-04, + 4.85742099408737208668e-04, + 4.59337829533421374787e-04, + 4.32694746982132956003e-04, + 4.05828286055327270860e-04, + 3.78753994909039224618e-04, + 3.51487526568311297540e-04, + 3.24044629888701042706e-04, + 2.96441140471124468109e-04, + 2.68692971535064537448e-04, + 2.40816104755891792965e-04, + 2.12826581070915530529e-04, + 1.84740491459934620937e-04, + 1.56573967705388389718e-04, + 1.28343173137436734367e-04, + 1.00064293369274724200e-04, + 7.17535270279865756201e-05, + 4.34270764862388947451e-05, + 1.51011386001131606149e-05, +-1.32081045416696524620e-05, +-4.14844948516519899375e-05, +-6.97119074558447989051e-05, +-9.78742598787180241452e-05, +-1.25955521195249200029e-04, +-1.53939721145969320030e-04, +-1.81810959208852370795e-04, +-2.09553413623342002373e-04, +-2.37151350361132772252e-04, +-2.64589132039119191708e-04, +-2.91851226768812584828e-04, +-3.18922216937715912854e-04, +-3.45786807917504923019e-04, +-3.72429836694131806071e-04, +-3.98836280414924259936e-04, +-4.24991264848284251536e-04, +-4.50880072750091832195e-04, +-4.76488152133843997395e-04, +-5.01801124438317467692e-04, +-5.26804792589028771099e-04, +-5.51485148948722817865e-04, +-5.75828383152479162180e-04, +-5.99820889823062712923e-04, +-6.23449276162207780341e-04, +-6.46700369413619538528e-04, +-6.69561224193530326286e-04, +-6.92019129684716838985e-04, +-7.14061616690151953514e-04, +-7.35676464541983651108e-04, +-7.56851707862541919249e-04, +-7.77575643173267975865e-04, +-7.97836835348055277602e-04, +-8.17624123907448297453e-04, +-8.36926629150230058478e-04, +-8.55733758119046612582e-04, +-8.74035210396826049359e-04, +-8.91820983730703649786e-04, +-9.09081379480705491225e-04, +-9.25807007889788277297e-04, +-9.41988793172909236878e-04, +-9.57617978421671824096e-04, +-9.72686130322748202653e-04, +-9.87185143686923052483e-04, +-1.00110724578650659398e-03, +-1.01444500049902323544e-03, +-1.02719131225463187161e-03, +-1.03933942978544770035e-03, +-1.05088294967471814964e-03, +-1.06181581970400955479e-03, +-1.07213234199665663482e-03, +-1.08182717595588814667e-03, +-1.09089534099611235214e-03, +-1.09933221906604130548e-03, +-1.10713355696224189685e-03, +-1.11429546843220921015e-03, +-1.12081443606577282543e-03, +-1.12668731297399537551e-03, +-1.13191132425482891832e-03, +-1.13648406824482742922e-03, +-1.14040351755644074963e-03, +-1.14366801990044438496e-03, +-1.14627629869328028812e-03, +-1.14822745344909417364e-03, +-1.14952095995648801048e-03, +-1.15015667024007182777e-03, +-1.15013481230698852258e-03, +-1.14945598967880415094e-03, +-1.14812118070920518922e-03, +-1.14613173768805766059e-03, +-1.14348938573257991221e-03, +-1.14019622146641639096e-03, +-1.13625471148757692386e-03, +-1.13166769062629166132e-03, +-1.12643835999398341310e-03, +-1.12057028482466340680e-03, +-1.11406739211015104116e-03, +-1.10693396803060797873e-03, +-1.09917465518223384131e-03, +-1.09079444960363011567e-03, +-1.08179869760285343912e-03, +-1.07219309238717466423e-03, +-1.06198367049757311231e-03, +-1.05117680805022224028e-03, +-1.03977921678728496210e-03, +-1.02779793993942468629e-03, +-1.01524034790259534006e-03, +-1.00211413373173349912e-03, +-9.88427308454093486029e-04, +-9.74188196205089573972e-04, +-9.59405429189479725879e-04, +-9.44087942471171881302e-04, +-9.28244968594481583042e-04, +-9.11886032040267347637e-04, +-8.95020943520216660794e-04, +-8.77659794112658803340e-04, +-8.59812949243432501564e-04, +-8.41491042515366753467e-04, +-8.22704969390060901480e-04, +-8.03465880725650455872e-04, +-7.83785176174564036933e-04, +-7.63674497444838786334e-04, +-7.43145721429159210325e-04, +-7.22210953206033133382e-04, +-7.00882518916405724239e-04, +-6.79172958520581071529e-04, +-6.57095018439407888011e-04, +-6.34661644084213061485e-04, +-6.11885972279487986777e-04, +-5.88781323583261557639e-04, +-5.65361194509265800601e-04, +-5.41639249655565977945e-04, +-5.17629313744230818220e-04, +-4.93345363576712316218e-04, +-4.68801519909265351684e-04, +-4.44012039254113445412e-04, +-4.18991305609581871604e-04, +-3.93753822125390276140e-04, +-3.68314202707166818418e-04, +-3.42687163565271075971e-04, +-3.16887514712763855660e-04, +-2.90930151417445159289e-04, +-2.64830045612876889462e-04, +-2.38602237273343473298e-04, +-2.12261825757707105287e-04, +-1.85823961127170580662e-04, +-1.59303835441746181271e-04, +-1.32716674040886725835e-04, +-1.06077726812662281766e-04, +-7.94022594569434886792e-05, +-5.27055447474102572785e-05, +-2.60028537974079832656e-05, + 6.90552665357526391948e-07, + 2.73594330103061967382e-05, + 5.39885733967170351332e-05, + 8.05627964425661594961e-05, + 1.07066969865010061308e-04, + 1.33486015086968664006e-04, + 1.59804915805331028064e-04, + 1.86008726516105670021e-04, + 2.12082580990773740320e-04, + 2.38011700700330354344e-04, + 2.63781403181116572490e-04, + 2.89377110338554649482e-04, + 3.14784356683413138554e-04, + 3.39988797496425883184e-04, + 3.64976216916463994978e-04, + 3.89732535947750265582e-04, + 4.14243820381606571868e-04, + 4.38496288628281076592e-04, + 4.62476319454435203307e-04, + 4.86170459622126181851e-04, + 5.09565431424569481242e-04, + 5.32648140115051980069e-04, + 5.55405681224405362376e-04, + 5.77825347763134713856e-04, + 5.99894637304163990538e-04, + 6.21601258942250942466e-04, + 6.42933140126212003714e-04, + 6.63878433360159405340e-04, + 6.84425522770043840912e-04, + 7.04563030531877763050e-04, + 7.24279823158044638691e-04, + 7.43565017638393201127e-04, + 7.62407987432378152909e-04, + 7.80798368309418419284e-04, + 7.98726064033930863682e-04, + 8.16181251892069835503e-04, + 8.33154388057122906319e-04, + 8.49636212790671986259e-04, + 8.65617755476581307410e-04, + 8.81090339485367181512e-04, + 8.96045586865937618293e-04, + 9.10475422862473118477e-04, + 9.24372080253872034986e-04, + 9.37728103513655198570e-04, + 9.50536352787640661209e-04, + 9.62790007687844002875e-04, + 9.74482570900335833865e-04, + 9.85607871605071426957e-04, + 9.96160068706062381411e-04, + 1.00613365387018584458e-03, + 1.01552345437301723939e-03, + 1.02432463575029123783e-03, + 1.03253270425362076584e-03, + 1.04014350910924206067e-03, + 1.04715324457870439731e-03, + 1.05355845182046950481e-03, + 1.05935602055159754607e-03, + 1.06454319050862085752e-03, + 1.06911755270714466277e-03, + 1.07307705049946027105e-03, + 1.07641998042986067850e-03, + 1.07914499288730056890e-03, + 1.08125109255521835092e-03, + 1.08273763865848467007e-03, + 1.08360434500746525242e-03, + 1.08385127983937892479e-03, + 1.08347886545726241128e-03, + 1.08248787766686694993e-03, + 1.08087944501203837150e-03, + 1.07865504780918649262e-03, + 1.07581651698158585126e-03, + 1.07236603269432462238e-03, + 1.06830612279092259861e-03, + 1.06363966103263283235e-03, + 1.05836986514164428132e-03, + 1.05250029464946915324e-03, + 1.04603484855193525419e-03, + 1.03897776277230035648e-03, + 1.03133360743408474848e-03, + 1.02310728394540504521e-03, + 1.01430402189651124034e-03, + 1.00492937577281401564e-03, + 9.94989221484924961370e-04, + 9.84489752718325020209e-04, + 9.73437477104688721023e-04, + 9.61839212217239581185e-04, + 9.49702081392630992861e-04, + 9.37033509381853305618e-04, + 9.23841217832837061606e-04, + 9.10133220607474814970e-04, + 8.95917818935899651529e-04, + 8.81203596410921950570e-04, + 8.65999413825665684263e-04, + 8.50314403857379305478e-04, + 8.34157965600880913111e-04, + 8.17539758954521347464e-04, + 8.00469698862303906568e-04, + 7.82957949415445273941e-04, + 7.65014917816926143072e-04, + 7.46651248212579373396e-04, + 7.27877815392361849668e-04, + 7.08705718365645193080e-04, + 6.89146273814000625765e-04, + 6.69211009425744215821e-04, + 6.48911657115913286138e-04, + 6.28260146135471188311e-04, + 6.07268596074486536641e-04, + 5.85949309762400622446e-04, + 5.64314766070410454152e-04, + 5.42377612619488803404e-04, + 5.20150658398866173708e-04, + 4.97646866298883240425e-04, + 4.74879345562723338432e-04, + 4.51861344161378882325e-04, + 4.28606241096286539726e-04, + 4.05127538634095468555e-04, + 3.81438854478096842863e-04, + 3.57553913880674515205e-04, + 3.33486541701773307050e-04, + 3.09250654417399727884e-04, + 2.84860252083193681537e-04, + 2.60329410257538723227e-04, + 2.35672271888895488046e-04, + 2.10903039172021308919e-04, + 1.86035965377764900275e-04, + 1.61085346661131244934e-04, + 1.36065513852313800395e-04, + 1.10990824235409179101e-04, + 8.58756533195474008359e-05, + 6.07343866069771497630e-05, + 3.55814113632548241332e-05, + 1.04311083936491137648e-05, +-1.47021561691009029690e-05, +-3.98040390611660384779e-05, +-6.48602280634465855726e-05, +-8.98564501522054298295e-05, +-1.14778479619700933784e-04, +-1.39612146160650535745e-04, +-1.64343342919338251907e-04, +-1.88958034493250977151e-04, +-2.13442264888526227673e-04, +-2.37782165422681623619e-04, +-2.61963962570504571396e-04, +-2.85973985747828166135e-04, +-3.09798675029788052153e-04, +-3.33424588798768176210e-04, +-3.56838411317501760876e-04, +-3.80026960223441392147e-04, +-4.02977193940015090100e-04, +-4.25676219000628282361e-04, +-4.48111297281314371974e-04, +-4.70269853137984079287e-04, +-4.92139480444267647663e-04, +-5.13707949526006615523e-04, +-5.34963213988673739162e-04, +-5.55893417433529703382e-04, +-5.76486900059300605252e-04, +-5.96732205145306224443e-04, +-6.16618085412612730242e-04, +-6.36133509259657436812e-04, +-6.55267666868877677634e-04, +-6.74009976180998601758e-04, +-6.92350088733664401595e-04, +-7.10277895361227803138e-04, +-7.27783531752448681514e-04, +-7.44857383863318112810e-04, +-7.61490093181871590539e-04, +-7.77672561841829005844e-04, +-7.93395957582958798182e-04, +-8.08651718554891877494e-04, +-8.23431557962021757127e-04, +-8.37727468546858129381e-04, +-8.51531726909685537062e-04, +-8.64836897661822056639e-04, +-8.77635837410563617207e-04, +-8.89921698573554803210e-04, +-9.01687933020594461521e-04, +-9.12928295540940920420e-04, +-9.23636847134304576554e-04, +-9.33807958123846902805e-04, +-9.43436311089422422263e-04, +-9.52516903619767376157e-04, +-9.61045050882069389411e-04, +-9.69016388007670759208e-04, +-9.76426872292704612667e-04, +-9.83272785212578647254e-04, +-9.89550734249325901482e-04, +-9.95257654530941207952e-04, +-1.00039081028195663871e-03, +-1.00494779608456845030e-03, +-1.00892653794981169979e-03, +-1.01232529419831556589e-03, +-1.01514265615029741774e-03, +-1.01737754862461565394e-03, +-1.01902923024675272530e-03, +-1.02009729356571554777e-03, +-1.02058166497997625417e-03, +-1.02048260447267446181e-03, +-1.01980070515639048741e-03, +-1.01853689262794660890e-03, +-1.01669242413375375544e-03, +-1.01426888754638775715e-03, +-1.01126820015312980997e-03, +-1.00769260725730729240e-03, +-1.00354468059351414899e-03, +-9.98827316557644555306e-04, +-9.93543734253049580854e-04, +-9.87697473353981499761e-04, +-9.81292391787839295494e-04, +-9.74332663237617449883e-04, +-9.66822774466185295462e-04, +-9.58767522464084383411e-04, +-9.50172011422648630022e-04, +-9.41041649534305781055e-04, +-9.31382145622106083493e-04, +-9.21199505600451087374e-04, +-9.10500028769397197308e-04, +-8.99290303944565551711e-04, +-8.87577205425210550085e-04, +-8.75367888802800289162e-04, +-8.62669786612691802744e-04, +-8.49490603831530729194e-04, +-8.35838313223061083780e-04, +-8.21721150535182709787e-04, +-8.07147609551117617942e-04, +-7.92126436997654084955e-04, +-7.76666627313488014232e-04, +-7.60777417280939101916e-04, +-7.44468280523723365504e-04, +-7.27748921874987655251e-04, +-7.10629271617923522104e-04, +-6.93119479603028368700e-04, +-6.75229909245266381526e-04, +-6.56971131404673501161e-04, +-6.38353918154137712354e-04, +-6.19389236437722294319e-04, +-6.00088241623651132139e-04, +-5.80462270955458170714e-04, +-5.60522836905225714695e-04, +-5.40281620432863491331e-04, +-5.19750464155060228240e-04, +-4.98941365428588355299e-04, +-4.77866469351204028841e-04, +-4.56538061684547645785e-04, +-4.34968561703376289593e-04, +-4.13170514974962768510e-04, +-3.91156586073003096314e-04, +-3.68939551230221718554e-04, +-3.46532290933948842939e-04, +-3.23947782468940600423e-04, +-3.01199092411757270073e-04, +-2.78299369081070745603e-04, +-2.55261834948078349290e-04, +-2.32099779011821834730e-04, +-2.08826549143248190420e-04, +-1.85455544402832308909e-04, +-1.62000207336008043239e-04, +-1.38474016250865456347e-04, +-1.14890477482541928256e-04, +-9.12631176487416705644e-05, +-6.76054759008182519671e-05, +-4.39310961748295172825e-05, +-2.02535194471571128164e-05, + 3.41372400124625000704e-06, + 2.70571223073466086593e-05, + 5.06631897304295544804e-05, + 7.42184743349819369285e-05, + 9.77095656468657952631e-05, + 1.21123102278798669873e-04, + 1.44445779520586308278e-04, + 1.67664356890219484351e-04, + 1.90765665640995252163e-04, + 2.13736616220833977771e-04, + 2.36564205679401197901e-04, + 2.59235525018876972973e-04, + 2.81737766484226406522e-04, + 3.04058230788827618760e-04, + 3.26184334271549601202e-04, + 3.48103615980852423070e-04, + 3.69803744682461728397e-04, + 3.91272525786277706496e-04, + 4.12497908188799451267e-04, + 4.33467991027201371770e-04, + 4.54171030341281908426e-04, + 4.74595445639567638761e-04, + 4.94729826365895158924e-04, + 5.14562938262885013335e-04, + 5.34083729628744225196e-04, + 5.53281337463915729412e-04, + 5.72145093504289737989e-04, + 5.90664530137289503671e-04, + 6.08829386198019386657e-04, + 6.26629612641936822176e-04, + 6.44055378091031721643e-04, + 6.61097074250476457111e-04, + 6.77745321192732130128e-04, + 6.93990972506254143876e-04, + 7.09825120305858456998e-04, + 7.25239100102302775876e-04, + 7.40224495528040305620e-04, + 7.54773142916835191284e-04, + 7.68877135734856572910e-04, + 7.82528828860328353779e-04, + 7.95720842710183188552e-04, + 8.08446067210845170301e-04, + 8.20697665611487049177e-04, + 8.32469078137362318050e-04, + 8.43754025481521134980e-04, + 8.54546512132969143805e-04, + 8.64840829539518206326e-04, + 8.74631559103689298733e-04, + 8.83913575010109465319e-04, + 8.92682046882942626005e-04, + 9.00932442271964615751e-04, + 9.08660528966120082696e-04, + 9.15862377133194608195e-04, + 9.22534361284796920223e-04, + 9.28673162065495115362e-04, + 9.34275767865342418421e-04, + 9.39339476254983990131e-04, + 9.43861895242741424407e-04, + 9.47840944353070817725e-04, + 9.51274855525978185397e-04, + 9.54162173837028583338e-04, + 9.56501758037713121358e-04, + 9.58292780916003973483e-04, + 9.59534729477142054460e-04, + 9.60227404944570409398e-04, + 9.60370922581348226629e-04, + 9.59965711332194985249e-04, + 9.59012513286591154055e-04, + 9.57512382963391348902e-04, + 9.55466686417531189252e-04, + 9.52877100169494421419e-04, + 9.49745609958331992936e-04, + 9.46074509319091115633e-04, + 9.41866397985661216001e-04, + 9.37124180120078799534e-04, + 9.31851062369440700205e-04, + 9.26050551751833660001e-04, + 9.19726453372463970473e-04, + 9.12882867971548752663e-04, + 9.05524189305535872827e-04, + 8.97655101363274135137e-04, + 8.89280575418887665219e-04, + 8.80405866923194158763e-04, + 8.71036512235576058406e-04, + 8.61178325198361390401e-04, + 8.50837393555776847279e-04, + 8.40020075219696923594e-04, + 8.28732994384399467708e-04, + 8.16983037492857960653e-04, + 8.04777349056774379821e-04, + 7.92123327333073561259e-04, + 7.79028619859369530695e-04, + 7.65501118851119729744e-04, + 7.51548956463218408713e-04, + 7.37180499918858086333e-04, + 7.22404346508583494919e-04, + 7.07229318462486390359e-04, + 6.91664457698695713146e-04, + 6.75719020451036778314e-04, + 6.59402471779397571228e-04, + 6.42724479965596788740e-04, + 6.25694910798709228936e-04, + 6.08323821752458095656e-04, + 5.90621456058646517734e-04, + 5.72598236680009584250e-04, + 5.54264760185757283245e-04, + 5.35631790533803520474e-04, + 5.16710252763027825043e-04, + 4.97511226599373773682e-04, + 4.78045939979498718704e-04, + 4.58325762495759227340e-04, + 4.38362198766371338136e-04, + 4.18166881734467700462e-04, + 3.97751565900299880723e-04, + 3.77128120490046988070e-04, + 3.56308522565547207937e-04, + 3.35304850078806907388e-04, + 3.14129274875331928468e-04, + 2.92794055650324276316e-04, + 2.71311530861826331624e-04, + 2.49694111604887615530e-04, + 2.27954274450881122505e-04, + 2.06104554256081410344e-04, + 1.84157536943679384566e-04, + 1.62125852263222448597e-04, + 1.40022166532036894350e-04, + 1.17859175362270858218e-04, + 9.56495963781261012088e-05, + 7.34061619272917469060e-05, + 5.11416117907757448134e-05, + 2.88686858953092775838e-05, + 6.60011703245474962544e-06, +-1.56513764112641267506e-05, +-3.78730977094623622752e-05, +-6.00523790315616779367e-05, +-8.21765886552515715992e-05, +-1.04233138151800156347e-04, +-1.26209489539367793924e-04, +-1.48093162401345972059e-04, +-1.69871740964736657117e-04, +-1.91532881135268300563e-04, +-2.13064317484699505389e-04, +-2.34453870186744113427e-04, +-2.55689451897549299090e-04, +-2.76759074576870677410e-04, +-2.97650856246099086537e-04, +-3.18353027679335392423e-04, +-3.38853939023753682018e-04, +-3.59142066345504676773e-04, +-3.79206018097636495413e-04, +-3.99034541506046805132e-04, +-4.18616528870369446116e-04, +-4.37941023775921783445e-04, +-4.56997227213373118440e-04, +-4.75774503602719464699e-04, +-4.94262386718192386383e-04, +-5.12450585510814218305e-04, +-5.30328989825377310544e-04, +-5.47887676008649280625e-04, +-5.65116912405763628310e-04, +-5.82007164741549449030e-04, +-5.98549101384425463745e-04, +-6.14733598488893004212e-04, +-6.30551745014977364258e-04, +-6.45994847621079656963e-04, +-6.61054435427856318212e-04, +-6.75722264650496957927e-04, +-6.89990323096750768871e-04, +-7.03850834528551736954e-04, +-7.17296262884492574242e-04, +-7.30319316361157646819e-04, +-7.42912951350982778652e-04, +-7.55070376234532832961e-04, +-7.66785055025333219143e-04, +-7.78050710864884066675e-04, +-7.88861329366501596444e-04, +-7.99211161806001623743e-04, +-8.09094728157404166971e-04, +-8.18506819972308029276e-04, +-8.27442503101282920627e-04, +-8.35897120255950105278e-04, +-8.43866293410389599859e-04, +-8.51345926040684010221e-04, +-8.58332205201442922232e-04, +-8.64821603438301273262e-04, +-8.70810880535423945462e-04, +-8.76297085097227715367e-04, +-8.81277555963454932789e-04, +-8.85749923457110387506e-04, +-8.89712110464565414381e-04, +-8.93162333347438598848e-04, +-8.96099102685879683565e-04, +-8.98521223852970446835e-04, +-9.00427797420107569638e-04, +-9.01818219393255059504e-04, +-9.02692181280114911909e-04, +-9.03049669988348823954e-04, +-9.02890967555027251605e-04, +-9.02216650707655248853e-04, +-9.01027590257164317372e-04, +-8.99324950323396755253e-04, +-8.97110187393653770935e-04, +-8.94385049215033777793e-04, +-8.91151573521319268802e-04, +-8.87412086595320399006e-04, +-8.83169201667640974690e-04, +-8.78425817152939884119e-04, +-8.73185114724849367231e-04, +-8.67450557230792511539e-04, +-8.61225886448070839484e-04, +-8.54515120682583636733e-04, +-8.47322552211840669678e-04, +-8.39652744573696728503e-04, +-8.31510529702644309025e-04, +-8.22901004915378340120e-04, +-8.13829529747517842198e-04, +-8.04301722643430768052e-04, +-7.94323457501185689437e-04, +-7.83900860074752763550e-04, +-7.73040304235644501474e-04, +-7.61748408096249419140e-04, +-7.50032029997244466084e-04, +-7.37898264361402087853e-04, +-7.25354437416511968473e-04, +-7.12408102789705661648e-04, +-6.99067036976015396266e-04, +-6.85339234683824977817e-04, +-6.71232904059968502400e-04, +-6.56756461797351536944e-04, +-6.41918528127957059397e-04, +-6.26727921704332315012e-04, +-6.11193654372324123199e-04, +-5.95324925838475161287e-04, +-5.79131118235020063596e-04, +-5.62621790585767769452e-04, +-5.45806673175928220784e-04, +-5.28695661829722569208e-04, +-5.11298812098492927447e-04, +-4.93626333363000229307e-04, +-4.75688582853520537230e-04, +-4.57496059590992946043e-04, +-4.39059398252854521209e-04, +-4.20389362967140572426e-04, +-4.01496841038451060622e-04, +-3.82392836609444868555e-04, +-3.63088464261537163542e-04, +-3.43594942558548969210e-04, +-3.23923587536901721236e-04, +-3.04085806146491737303e-04, +-2.84093089645560742049e-04, +-2.63957006953748822640e-04, +-2.43689197967006995066e-04, +-2.23301366838275436311e-04, +-2.02805275227777953529e-04, +-1.82212735526838365925e-04, +-1.61535604059103902281e-04, +-1.40785774263093080554e-04, +-1.19975169859954066938e-04, +-9.91157380105508263764e-05, +-7.82194424651331946842e-05, +-5.72982567107504074688e-05, +-3.63641571189655019264e-05, +-1.54291160986802106125e-05, + 5.49490474234285622543e-06, + 2.63959614233348352161e-05, + 4.72621343997122955673e-05, + 6.80815353521026694937e-05, + 8.88423139508433642357e-05, + 1.09532664592484337918e-04, + 1.30140833104319903011e-04, + 1.50655123413172910328e-04, + 1.71063904174602321451e-04, + 1.91355615359099600053e-04, + 2.11518774790675712300e-04, + 2.31541984635477411745e-04, + 2.51413937835562545462e-04, + 2.71123424484858896975e-04, + 2.90659338143525736164e-04, + 3.10010682087186043628e-04, + 3.29166575487528168323e-04, + 3.48116259520795355564e-04, + 3.66849103400749643276e-04, + 3.85354610332733758284e-04, + 4.03622423385466462271e-04, + 4.21642331277442610968e-04, + 4.39404274074367811459e-04, + 4.56898348794905137527e-04, + 4.74114814921268088160e-04, + 4.91044099811763397334e-04, + 5.07676804012220281824e-04, + 5.24003706463404693612e-04, + 5.40015769601512427185e-04, + 5.55704144348954519501e-04, + 5.71060174992583653546e-04, + 5.86075403946940813073e-04, + 6.00741576399512768568e-04, + 6.15050644835952228101e-04, + 6.28994773442125574073e-04, + 6.42566342381337704884e-04, + 6.55757951943882421396e-04, + 6.68562426566777384153e-04, + 6.80972818721725897499e-04, + 6.92982412668881352959e-04, + 7.04584728074633746646e-04, + 7.15773523491389403184e-04, + 7.26542799697492522500e-04, + 7.36886802895533226179e-04, + 7.46800027767298055768e-04, + 7.56277220383868350323e-04, + 7.65313380969130045012e-04, + 7.73903766515502376799e-04, + 7.82043893250363385782e-04, + 7.89729538951949232121e-04, + 7.96956745113565389119e-04, + 8.03721818954994393636e-04, + 8.10021335280101820522e-04, + 8.15852138179731594357e-04, + 8.21211342579053417585e-04, + 8.26096335628634381720e-04, + 8.30504777938583372936e-04, + 8.34434604655206872172e-04, + 8.37884026379746372007e-04, + 8.40851529928737925421e-04, + 8.43335878935819161471e-04, + 8.45336114294710332107e-04, + 8.46851554443294471733e-04, + 8.47881795488795693763e-04, + 8.48426711174108750049e-04, + 8.48486452685477828516e-04, + 8.48061448301770160786e-04, + 8.47152402885697889713e-04, + 8.45760297217433587059e-04, + 8.43886387171142548884e-04, + 8.41532202735059621686e-04, + 8.38699546875822229616e-04, + 8.35390494247859852379e-04, + 8.31607389748687583081e-04, + 8.27352846921140154882e-04, + 8.22629746203563960195e-04, + 8.17441233029105799972e-04, + 8.11790715775362542797e-04, + 8.05681863565683954384e-04, + 7.99118603923527101411e-04, + 7.92105120281344542502e-04, + 7.84645849345590325717e-04, + 7.76745478319420114104e-04, + 7.68408941984943219712e-04, + 7.59641419646665534519e-04, + 7.50448331938106580861e-04, + 7.40835337493533463253e-04, + 7.30808329486818254554e-04, + 7.20373432039535070703e-04, + 7.09536996500486488726e-04, + 6.98305597598893957115e-04, + 6.86686029473570981770e-04, + 6.74685301580476909020e-04, + 6.62310634481180966239e-04, + 6.49569455514414613798e-04, + 6.36469394353982704203e-04, + 6.23018278454912912898e-04, + 6.09224128391051378099e-04, + 5.95095153086705442279e-04, + 5.80639744945168250270e-04, + 5.65866474877092448525e-04, + 5.50784087231426526705e-04, + 5.35401494632215197225e-04, + 5.19727772724077859492e-04, + 5.03772154829525923431e-04, + 4.87544026521280851084e-04, + 4.71052920112772989698e-04, + 4.54308509069835603569e-04, + 4.37320602347533553267e-04, + 4.20099138654383497463e-04, + 4.02654180648284807775e-04, + 3.84995909067011564137e-04, + 3.67134616796844961539e-04, + 3.49080702882780392719e-04, + 3.30844666483778653780e-04, + 3.12437100776581622944e-04, + 2.93868686811618183737e-04, + 2.75150187324561020918e-04, + 2.56292440507140670877e-04, + 2.37306353740675621137e-04, + 2.18202897296279266356e-04, + 1.98993098004925772883e-04, + 1.79688032901358264856e-04, + 1.60298822845364506793e-04, + 1.40836626124112224753e-04, + 1.21312632039215933556e-04, + 1.01738054482220324185e-04, + 8.21241255021581603984e-05, + 6.24820888690072755080e-05, + 4.28231936363832337185e-05, + 2.31586877076589681926e-05, + 3.49981140855670628566e-06, +-1.61422089292776860909e-05, +-3.57561673710188603244e-05, +-5.53308847633998468008e-05, +-7.48552150979509803470e-05, +-9.43180518494260796856e-05, +-1.13708334285348401584e-04, +-1.33015053743449631566e-04, +-1.52227259873300292507e-04, +-1.71334066838623079324e-04, +-1.90324659476782091653e-04, +-2.09188299411965425824e-04, +-2.27914331118587613423e-04, +-2.46492187931631313944e-04, +-2.64911398000205382339e-04, +-2.83161590181416034876e-04, +-3.01232499870904074039e-04, +-3.19113974766915017931e-04, +-3.36795980564636679867e-04, +-3.54268606577632174954e-04, +-3.71522071283203947009e-04, +-3.88546727788614181063e-04, +-4.05333069215096399290e-04, +-4.21871733996659933463e-04, +-4.38153511090731847231e-04, +-4.54169345097848065496e-04, +-4.69910341287265624979e-04, +-4.85367770526103374431e-04, +-5.00533074108989832485e-04, +-5.15397868485681603760e-04, +-5.29953949884007929905e-04, +-5.44193298825634374886e-04, +-5.58108084532057653962e-04, +-5.71690669218670195068e-04, +-5.84933612274217158006e-04, +-5.97829674323603708214e-04, +-6.10371821171734304026e-04, +-6.22553227626419856781e-04, +-6.34367281197839366289e-04, +-6.45807585673186250637e-04, +-6.56867964564019149454e-04, +-6.67542464424877488548e-04, +-6.77825358041074066233e-04, +-6.87711147484166077093e-04, +-6.97194567033422758773e-04, +-7.06270585961741746359e-04, +-7.14934411184561628694e-04, +-7.23181489770394637234e-04, +-7.31007511311650994522e-04, +-7.38408410154600355381e-04, +-7.45380367487197487489e-04, +-7.51919813283889650751e-04, +-7.58023428106295344038e-04, +-7.63688144758921860430e-04, +-7.68911149799110884596e-04, +-7.73689884900469453805e-04, +-7.78022048069176852536e-04, +-7.81905594712582730464e-04, +-7.85338738559663196610e-04, +-7.88319952432907605604e-04, +-7.90847968871373333856e-04, +-7.92921780604692572579e-04, +-7.94540640877896479737e-04, +-7.95704063626980471514e-04, +-7.96411823505323844020e-04, +-7.96663955761047642458e-04, +-7.96460755965521980358e-04, +-7.95802779593343299035e-04, +-7.94690841454150087575e-04, +-7.93126014976744679770e-04, +-7.91109631346083286806e-04, +-7.88643278493758549327e-04, +-7.85728799942701674856e-04, +-7.82368293506905928061e-04, +-7.78564109847002514854e-04, +-7.74318850882812310596e-04, +-7.69635368063673682044e-04, +-7.64516760497901438909e-04, +-7.58966372942442794175e-04, +-7.52987793654077996498e-04, +-7.46584852103500504379e-04, +-7.39761616553728774091e-04, +-7.32522391504357027643e-04, +-7.24871715003236934821e-04, +-7.16814355827273216350e-04, +-7.08355310534040027645e-04, +-6.99499800386016380889e-04, +-6.90253268149437163720e-04, +-6.80621374769529714592e-04, +-6.70609995924295360266e-04, +-6.60225218458873998675e-04, +-6.49473336702642350601e-04, +-6.38360848671277059801e-04, +-6.26894452156058273537e-04, +-6.15081040702747340251e-04, +-6.02927699482527735750e-04, +-5.90441701057256335301e-04, +-5.77630501041881037026e-04, +-5.64501733666179588388e-04, +-5.51063207239021373221e-04, +-5.37322899517202385612e-04, +-5.23288952982047124961e-04, +-5.08969670026456150538e-04, +-4.94373508055059602412e-04, +-4.79509074500653401096e-04, +-4.64385121759629336102e-04, +-4.49010542049456493497e-04, +-4.33394362191214064118e-04, +-4.17545738320244637712e-04, +-4.01473950527997305165e-04, +-3.85188397438232619108e-04, +-3.68698590720627130540e-04, +-3.52014149545262831995e-04, +-3.35144794980849110039e-04, +-3.18100344340219566650e-04, +-3.00890705476273645578e-04, +-2.83525871031688149124e-04, +-2.66015912645737500133e-04, +-2.48370975121568597112e-04, +-2.30601270557308229850e-04, +-2.12717072444391431304e-04, +-1.94728709736517952358e-04, +-1.76646560892675731939e-04, +-1.58481047897534086224e-04, +-1.40242630262970099540e-04, +-1.21941799013744982391e-04, +-1.03589070661107662103e-04, +-8.51949811676530225713e-05, +-6.67700799069139572109e-05, +-4.83249236211274086098e-05, +-2.98700703807564870525e-05, +-1.14160735488978414020e-05, + 7.02652424554682768497e-06, + 2.54471971228236679705e-05, + 4.38354419518023738413e-05, + 6.21807843308446069313e-05, + 8.04727845460066358498e-05, + 9.87010435040899136066e-05, + 1.16855208636383958460e-04, + 1.34924979770344443406e-04, + 1.52900114965400754944e-04, + 1.70770436309920342057e-04, + 1.88525835675920134431e-04, + 2.06156280428297997024e-04, + 2.23651819085366783272e-04, + 2.41002586927498689160e-04, + 2.58198811550729352172e-04, + 2.75230818362170949389e-04, + 2.92089036014278136209e-04, + 3.08764001774616207285e-04, + 3.25246366828520531121e-04, + 3.41526901511388200801e-04, + 3.57596500467790591720e-04, + 3.73446187734516289129e-04, + 3.89067121744707245228e-04, + 4.04450600250306482528e-04, + 4.19588065160076859831e-04, + 4.34471107290538996557e-04, + 4.49091471027067759818e-04, + 4.63441058892829452643e-04, + 4.77511936022862045707e-04, + 4.91296334540600198627e-04, + 5.04786657835014449663e-04, + 5.17975484735516645760e-04, + 5.30855573582563605717e-04, + 5.43419866191619145568e-04, + 5.55661491708522902247e-04, + 5.67573770353875343975e-04, + 5.79150217054632036016e-04, + 5.90384544960849454512e-04, + 6.01270668845691608206e-04, + 6.11802708386863214850e-04, + 6.21974991327834889066e-04, + 6.31782056516764687314e-04, + 6.41218656822146407942e-04, + 6.50279761923036299723e-04, + 6.58960560972716405566e-04, + 6.67256465134287500389e-04, + 6.75163109986891556320e-04, + 6.82676357801303567048e-04, + 6.89792299683732634992e-04, + 6.96507257586713749917e-04, + 7.02817786186088130918e-04, + 7.08720674623126924326e-04, + 7.14212948110944231481e-04, + 7.19291869404349885550e-04, + 7.23954940132546750399e-04, + 7.28199901993943090293e-04, + 7.32024737812592227876e-04, + 7.35427672455747746989e-04, + 7.38407173612188813538e-04, + 7.40961952430967151807e-04, + 7.43090964020374881993e-04, + 7.44793407806954867699e-04, + 7.46068727754538611394e-04, + 7.46916612443245453087e-04, + 7.47336995008605268868e-04, + 7.47330052940939869310e-04, + 7.46896207745253873714e-04, + 7.46036124461981245935e-04, + 7.44750711048991790794e-04, + 7.43041117625342466269e-04, + 7.40908735577333176642e-04, + 7.38355196527534156196e-04, + 7.35382371167495095879e-04, + 7.31992367954923252131e-04, + 7.28187531676248857131e-04, + 7.23970441875473923535e-04, + 7.19343911150391139564e-04, + 7.14310983317213688513e-04, + 7.08874931444885593435e-04, + 7.03039255760210023485e-04, + 6.96807681425207193181e-04, + 6.90184156188062745106e-04, + 6.83172847909139504749e-04, + 6.75778141963576887280e-04, + 6.68004638522109246875e-04, + 6.59857149711750939035e-04, + 6.51340696658104286593e-04, + 6.42460506411091959722e-04, + 6.33222008755997788076e-04, + 6.23630832911684193816e-04, + 6.13692804118148903594e-04, + 6.03413940115261806379e-04, + 5.92800447514970491047e-04, + 5.81858718069071527597e-04, + 5.70595324834820847096e-04, + 5.59017018240628819903e-04, + 5.47130722054300845832e-04, + 5.34943529255999883701e-04, + 5.22462697818653785606e-04, + 5.09695646398130772746e-04, + 4.96649949935782969619e-04, + 4.83333335176001986210e-04, + 4.69753676101234622468e-04, + 4.55918989287601634543e-04, + 4.41837429183325480515e-04, + 4.27517283312972833521e-04, + 4.12966967410454712222e-04, + 3.98195020483432121378e-04, + 3.83210099812103391695e-04, + 3.68020975885298450622e-04, + 3.52636527276817995143e-04, + 3.37065735465011645077e-04, + 3.21317679598622223548e-04, + 3.05401531211941905386e-04, + 2.89326548892257452619e-04, + 2.73102072902946376928e-04, + 2.56737519764977252090e-04, + 2.40242376800225943771e-04, + 2.23626196639659541874e-04, + 2.06898591699577582680e-04, + 1.90069228629096543095e-04, + 1.73147822732087712776e-04, + 1.56144132366777384441e-04, + 1.39067953326214697627e-04, + 1.21929113202958933396e-04, + 1.04737465740963099658e-04, + 8.75028851780528622514e-05, + 7.02352605825545112366e-05, + 5.29444901866215451251e-05, + 3.56404757200933205497e-05, + 1.83331167478597644273e-05, + 1.03230501413102183826e-06, +-1.62520812034707693762e-05, +-3.35101827263670735968e-05, +-5.07321650911279374628e-05, +-6.79082241459080256747e-05, +-8.50285916240537564164e-05, +-1.02083540691677796268e-04, +-1.19063391466316483881e-04, +-1.35958516502816118129e-04, +-1.52759346244455719837e-04, +-1.69456374435215186046e-04, +-1.86040163490673691061e-04, +-2.02501349824351403305e-04, +-2.18830649126511295058e-04, +-2.35018861592449355329e-04, +-2.51056877097335180617e-04, +-2.66935680314695194647e-04, +-2.82646355775669996281e-04, +-2.98180092866208153266e-04, +-3.13528190759385430846e-04, +-3.28682063280201183005e-04, +-3.43633243699864576997e-04, +-3.58373389457262059472e-04, +-3.72894286804705877604e-04, +-3.87187855375492433196e-04, +-4.01246152670716468933e-04, +-4.15061378462855390652e-04, +-4.28625879113702864826e-04, +-4.41932151804175915588e-04, +-4.54972848673900734286e-04, +-4.67740780867979507370e-04, +-4.80228922488919207114e-04, +-4.92430414451660788955e-04, +-5.04338568239140645766e-04, +-5.15946869556969272587e-04, +-5.27248981884690759263e-04, +-5.38238749922089398589e-04, +-5.48910202928370723023e-04, +-5.59257557952611700225e-04, +-5.69275222953672071884e-04, +-5.78957799807889249809e-04, +-5.88300087202963859455e-04, +-5.97297083416476414473e-04, +-6.05943988977575135647e-04, +-6.14236209210458085871e-04, +-6.22169356658183671412e-04, +-6.29739253385739618761e-04, +-6.36941933161007476510e-04, +-6.43773643512582892379e-04, +-6.50230847663354235948e-04, +-6.56310226338886878658e-04, +-6.62008679449682451920e-04, +-6.67323327646487897066e-04, +-6.72251513747878452071e-04, +-6.76790804039441285488e-04, +-6.80938989443917279398e-04, +-6.84694086561815564058e-04, +-6.88054338581924984468e-04, +-6.91018216061473023945e-04, +-6.93584417575499262779e-04, +-6.95751870235252118692e-04, +-6.97519730075439408322e-04, +-6.98887382310238512544e-04, +-6.99854441458020392307e-04, +-7.00420751334910186674e-04, +-7.00586384917250637808e-04, +-7.00351644073214348388e-04, +-6.99717059163839283017e-04, +-6.98683388513845408767e-04, +-6.97251617752650001102e-04, +-6.95422959026119487901e-04, +-6.93198850079607088379e-04, +-6.90580953212918528285e-04, +-6.87571154107985264316e-04, +-6.84171560529966103770e-04, +-6.80384500902708982788e-04, +-6.76212522759481789864e-04, +-6.71658391069967749057e-04, +-6.66725086444653041590e-04, +-6.61415803217692819561e-04, +-6.55733947409528573555e-04, +-6.49683134570482436268e-04, +-6.43267187506764773208e-04, +-6.36490133890204668257e-04, +-6.29356203753268024677e-04, +-6.21869826870875635171e-04, +-6.14035630030630393862e-04, +-6.05858434193134814082e-04, +-5.97343251544118505024e-04, +-5.88495282440187417530e-04, +-5.79319912250014150239e-04, +-5.69822708092951237674e-04, +-5.60009415476908612407e-04, +-5.49885954837576801033e-04, +-5.39458417981255439720e-04, +-5.28733064433041348440e-04, +-5.17716317692869828875e-04, +-5.06414761401502129881e-04, +-4.94835135418839880059e-04, +-4.82984331816689843164e-04, +-4.70869390788640387446e-04, +-4.58497496479242630431e-04, +-4.45875972735065601461e-04, +-4.33012278780107377589e-04, +-4.19914004818108983763e-04, +-4.06588867564375744564e-04, +-3.93044705709642795341e-04, +-3.79289475318866453699e-04, +-3.65331245167339706530e-04, +-3.51178192017081926713e-04, +-3.36838595836177763076e-04, +-3.22320834963867378347e-04, +-3.07633381224204521288e-04, +-2.92784794991132475261e-04, +-2.77783720207839526437e-04, +-2.62638879363297228237e-04, +-2.47359068428886473296e-04, +-2.31953151758071922503e-04, +-2.16430056951960250863e-04, +-2.00798769693994654060e-04, +-1.85068328556394910873e-04, +-1.69247819781622929874e-04, +-1.53346372041766269151e-04, +-1.37373151178878973033e-04, +-1.21337354929306262606e-04, +-1.05248207635004573535e-04, +-8.91149549450086627062e-05, +-7.29468585098004703403e-05, +-5.67531906719987081617e-05, +-4.05432291561632574743e-05, +-2.43262517606341878125e-05, +-8.11153105499568761387e-06, + 8.09167091459697115441e-06, + 2.42741079085157292628e-05, + 4.04265547626939556413e-05, + 5.65398126401744739798e-05, + 7.26047142624750100346e-05, + 8.86121291176844783554e-05, + 1.04552968642355261246e-04, + 1.20418191374254643930e-04, + 1.36198808073058146538e-04, + 1.51885886806070295480e-04, + 1.67470557996213817529e-04, + 1.82944019429153478633e-04, + 1.98297541217112740890e-04, + 2.13522470716304618504e-04, + 2.28610237395321440291e-04, + 2.43552357651734171758e-04, + 2.58340439574197757323e-04, + 2.72966187647394017187e-04, + 2.87421407397178490465e-04, + 3.01698009973331443285e-04, + 3.15788016667368121211e-04, + 3.29683563362888126455e-04, + 3.43376904915868638030e-04, + 3.56860419462906380220e-04, + 3.70126612654194222032e-04, + 3.83168121809794538692e-04, + 3.95977719996309473864e-04, + 4.08548320021925631847e-04, + 4.20872978347595460679e-04, + 4.32944898912126369117e-04, + 4.44757436869292204114e-04, + 4.56304102234621905294e-04, + 4.67578563440100960016e-04, + 4.78574650794741016362e-04, + 4.89286359849140845869e-04, + 4.99707854662346487480e-04, + 5.09833470968881633315e-04, + 5.19657719244667921921e-04, + 5.29175287669990585850e-04, + 5.38381044987819995518e-04, + 5.47270043256114818893e-04, + 5.55837520492576445640e-04, + 5.64078903210458873843e-04, + 5.71989808844079565542e-04, + 5.79566048062779125977e-04, + 5.86803626972093816082e-04, + 5.93698749201003678558e-04, + 6.00247817874220647612e-04, + 6.06447437468376929041e-04, + 6.12294415551340506093e-04, + 6.17785764403646210467e-04, + 6.22918702521296861058e-04, + 6.27690655999173577340e-04, + 6.32099259794388049390e-04, + 6.36142358868971454465e-04, + 6.39818009211379277838e-04, + 6.43124478736333145788e-04, + 6.46060248062606972720e-04, + 6.48624011168465121509e-04, + 6.50814675924448241516e-04, + 6.52631364503392400953e-04, + 6.54073413667472913086e-04, + 6.55140374932347883084e-04, + 6.55832014608344012786e-04, + 6.56148313718822465482e-04, + 6.56089467795875169558e-04, + 6.55655886553618491575e-04, + 6.54848193439355763003e-04, + 6.53667225063030848942e-04, + 6.52114030505376840972e-04, + 6.50189870505314443556e-04, + 6.47896216527166549613e-04, + 6.45234749708334539252e-04, + 6.42207359688187111660e-04, + 6.38816143318927205305e-04, + 6.35063403259281166260e-04, + 6.30951646451974345643e-04, + 6.26483582485939526248e-04, + 6.21662121844317769152e-04, + 6.16490374039393236767e-04, + 6.10971645635609837167e-04, + 6.05109438161931267354e-04, + 5.98907445914837149696e-04, + 5.92369553653347702404e-04, + 5.85499834187430895707e-04, + 5.78302545861415578064e-04, + 5.70782129933787834436e-04, + 5.62943207855098252772e-04, + 5.54790578445580164282e-04, + 5.46329214974210436787e-04, + 5.37564262140980504354e-04, + 5.28501032964188142450e-04, + 5.19145005574684313687e-04, + 5.09501819918850898904e-04, + 4.99577274372495932532e-04, + 4.89377322267549059315e-04, + 4.78908068333559408525e-04, + 4.68175765056459951968e-04, + 4.57186808956279780707e-04, + 4.45947736786433599192e-04, + 4.34465221656520647706e-04, + 4.22746069081200064391e-04, + 4.10797212957284853512e-04, + 3.98625711471500149014e-04, + 3.86238742941308148531e-04, + 3.73643601591243563771e-04, + 3.60847693267234983453e-04, + 3.47858531091431943082e-04, + 3.34683731060088070306e-04, + 3.21331007586994784036e-04, + 3.07808168995286370300e-04, + 2.94123112959944975862e-04, + 2.80283821903894213648e-04, + 2.66298358350258257497e-04, + 2.52174860233517097834e-04, + 2.37921536172264099776e-04, + 2.23546660706324561889e-04, + 2.09058569500978578149e-04, + 1.94465654521075659777e-04, + 1.79776359177804124882e-04, + 1.64999173451064800808e-04, + 1.50142628989783814353e-04, + 1.35215294193867887652e-04, + 1.20225769279667712834e-04, + 1.05182681332417253214e-04, + 9.00946793482652321869e-05, + 7.49704292687580406678e-05, + 5.98186090107322883933e-05, + 4.46479034941903122767e-05, + 2.94669996713655661538e-05, + 1.42845815595480592387e-05, +-8.90674719386678467731e-07, +-1.60501058898957495679e-05, +-3.11850664615309880164e-05, +-4.62869336522098696559e-05, +-6.13471122938098376541e-05, +-7.63570397170260420881e-05, +-9.13081906125804212970e-05, +-1.06192081866257116186e-04, +-1.21000277364919335359e-04, +-1.35724392770807756941e-04, +-1.50356100261421840461e-04, +-1.64887133232308251375e-04, +-1.79309290960107407722e-04, +-1.93614443223211164184e-04, +-2.07794534877538741033e-04, +-2.21841590384600493343e-04, +-2.35747718289653712892e-04, +-2.49505115647181735690e-04, +-2.63106072391320949463e-04, +-2.76542975648779115836e-04, +-2.89808313991833633137e-04, +-3.02894681629039077587e-04, +-3.15794782531314804225e-04, +-3.28501434491123775472e-04, +-3.41007573112413263187e-04, +-3.53306255729321028528e-04, +-3.65390665251150495701e-04, +-3.77254113931894290764e-04, +-3.88890047061697880296e-04, +-4.00292046578829127310e-04, +-4.11453834599746401911e-04, +-4.22369276865425247180e-04, +-4.33032386102221345144e-04, +-4.43437325295184645198e-04, +-4.53578410872218030017e-04, +-4.63450115797292723756e-04, +-4.73047072571043994947e-04, +-4.82364076137125729737e-04, +-4.91396086692756878071e-04, +-5.00138232402001195638e-04, +-5.08585812010168398199e-04, +-5.16734297358173813065e-04, +-5.24579335795330296312e-04, +-5.32116752489386786451e-04, +-5.39342552632568559418e-04, +-5.46252923542469171619e-04, +-5.52844236656707828902e-04, +-5.59113049420296060084e-04, +-5.65056107064770439183e-04, +-5.70670344278172711819e-04, +-5.75952886765007470403e-04, +-5.80901052695480778210e-04, +-5.85512354043150645873e-04, +-5.89784497810519033403e-04, +-5.93715387141844816964e-04, +-5.97303122322707935599e-04, +-6.00546001665863931999e-04, +-6.03442522282995321911e-04, +-6.05991380742033013650e-04, +-6.08191473609774341941e-04, +-6.10041897879654818233e-04, +-6.11541951284462828586e-04, +-6.12691132494012132698e-04, +-6.13489141197734759101e-04, +-6.13935878072276153793e-04, +-6.14031444634213687678e-04, +-6.13776142978129783147e-04, +-6.13170475400273522204e-04, +-6.12215143908160716602e-04, +-6.10911049616502535922e-04, +-6.09259292029921744813e-04, +-6.07261168212986615807e-04, +-6.04918171848152540562e-04, +-6.02231992182249067230e-04, +-5.99204512862249404591e-04, +-5.95837810661095862788e-04, +-5.92134154094380829765e-04, +-5.88096001928879556775e-04, +-5.83726001583780864344e-04, +-5.79026987425731846405e-04, +-5.74001978958720709967e-04, +-5.68654178909981699100e-04, +-5.62986971213088379512e-04, +-5.57003918889516810679e-04, +-5.50708761829973685031e-04, +-5.44105414476881875038e-04, +-5.37197963409420707961e-04, +-5.29990664832675931022e-04, +-5.22487941972209408471e-04, +-5.14694382376049554099e-04, +-5.06614735125277882745e-04, +-4.98253907955200866543e-04, +-4.89616964288741747524e-04, +-4.80709120183835873340e-04, +-4.71535741196723874168e-04, +-4.62102339162885156296e-04, +-4.52414568897704873120e-04, +-4.42478224818736978665e-04, +-4.32299237491589249602e-04, +-4.21883670101533790608e-04, +-4.11237714852763253538e-04, +-4.00367689297795705319e-04, +-3.89280032598777342174e-04, +-3.77981301723072956981e-04, +-3.66478167575481482855e-04, +-3.54777411069201974430e-04, +-3.42885919137923399647e-04, +-3.30810680691371770349e-04, +-3.18558782516682129776e-04, +-3.06137405127995278469e-04, +-2.93553818566704544622e-04, +-2.80815378154804305266e-04, +-2.67929520203833435379e-04, +-2.54903757681815789065e-04, +-2.41745675840952941541e-04, +-2.28462927808299829519e-04, +-2.15063230142214405812e-04, +-2.01554358357060797247e-04, +-1.87944142418778622041e-04, +-1.74240462213917245062e-04, +-1.60451242994757493389e-04, +-1.46584450803131455471e-04, +-1.32648087875677540707e-04, +-1.18650188032929176604e-04, +-1.04598812055253963184e-04, +-9.05020430478532816746e-05, +-7.63679817980816182978e-05, +-6.22047421270673621006e-05, +-4.80204462387773454404e-05, +-3.38232200690939612160e-05, +-1.96211886373398563383e-05, +-5.42247140324502025757e-06, + 8.76482236824777340069e-06, + 2.29325982315957407963e-05, + 3.70727811720706265371e-05, + 5.11773202013517019616e-05, + 6.52381929346686494130e-05, + 7.92474101469974555583e-05, + 9.31970203054730103771e-05, + 1.07079114075787359224e-04, + 1.20885828799772198955e-04, + 1.34609352941733671338e-04, + 1.48241930501015857979e-04, + 1.61775865388299365999e-04, + 1.75203525763176128777e-04, + 1.88517348330553255508e-04, + 2.01709842593477496403e-04, + 2.14773595059988993677e-04, + 2.27701273401630213721e-04, + 2.40485630561381157630e-04, + 2.53119508808481513077e-04, + 2.65595843738193170946e-04, + 2.77907668214037251522e-04, + 2.90048116250403941428e-04, + 3.02010426833358551230e-04, + 3.13787947677527593714e-04, + 3.25374138916987524356e-04, + 3.36762576728041407650e-04, + 3.47946956882078583737e-04, + 3.58921098226289516687e-04, + 3.69678946090518610861e-04, + 3.80214575618283698918e-04, + 3.90522195020292855420e-04, + 4.00596148748304063669e-04, + 4.10430920588102858375e-04, + 4.20021136669482232032e-04, + 4.29361568391889935302e-04, + 4.38447135263920031219e-04, + 4.47272907655273392787e-04, + 4.55834109459644649508e-04, + 4.64126120667108176508e-04, + 4.72144479844627002613e-04, + 4.79884886523366084934e-04, + 4.87343203491520887780e-04, + 4.94515458991510439488e-04, + 5.01397848820237619291e-04, + 5.07986738331495536053e-04, + 5.14278664339342934768e-04, + 5.20270336921509223872e-04, + 5.25958641121905003633e-04, + 5.31340638551345634602e-04, + 5.36413568885707545825e-04, + 5.41174851260732862543e-04, + 5.45622085562818821651e-04, + 5.49753053615153054572e-04, + 5.53565720258578693874e-04, + 5.57058234326825011708e-04, + 5.60228929515402870182e-04, + 5.63076325144043553055e-04, + 5.65599126812190268823e-04, + 5.67796226947321581655e-04, + 5.69666705245914757952e-04, + 5.71209829006884771928e-04, + 5.72425053357448988464e-04, + 5.73312021371367866798e-04, + 5.73870564079618605650e-04, + 5.74100700373610150010e-04, + 5.74002636801101105701e-04, + 5.73576767255045208427e-04, + 5.72823672555648950346e-04, + 5.71744119926011510821e-04, + 5.70339062361724402107e-04, + 5.68609637894926635629e-04, + 5.66557168753326501759e-04, + 5.64183160414795923689e-04, + 5.61489300558173053124e-04, + 5.58477457910976646596e-04, + 5.55149680994817618443e-04, + 5.51508196769305851677e-04, + 5.47555409175347492477e-04, + 5.43293897578766660054e-04, + 5.38726415115223450716e-04, + 5.33855886937539434942e-04, + 5.28685408366441232306e-04, + 5.23218242945951541104e-04, + 5.17457820404608101993e-04, + 5.11407734523782039546e-04, + 5.05071740914395756958e-04, + 4.98453754703430222672e-04, + 4.91557848131608235084e-04, + 4.84388248063773933609e-04, + 4.76949333413366201133e-04, + 4.69245632482725018135e-04, + 4.61281820220592905877e-04, + 4.53062715398815335326e-04, + 4.44593277709539084434e-04, + 4.35878604784927761902e-04, + 4.26923929141124992512e-04, + 4.17734615048157432570e-04, + 4.08316155327850989487e-04, + 3.98674168081502775223e-04, + 3.88814393349325734903e-04, + 3.78742689703628627584e-04, + 3.68465030777748246259e-04, + 3.57987501732803619064e-04, + 3.47316295664270213630e-04, + 3.36457709950689946247e-04, + 3.25418142546407844398e-04, + 3.14204088220705103369e-04, + 3.02822134745452705828e-04, + 2.91278959033536570707e-04, + 2.79581323230313654512e-04, + 2.67736070760376913824e-04, + 2.55750122331942382741e-04, + 2.43630471901182189993e-04, + 2.31384182598852114476e-04, + 2.19018382621588081956e-04, + 2.06540261090263434262e-04, + 1.93957063877727543073e-04, + 1.81276089408560325388e-04, + 1.68504684432981764438e-04, + 1.55650239777576011087e-04, + 1.42720186075200863515e-04, + 1.29721989476556069784e-04, + 1.16663147345869003713e-04, + 1.03551183943265592683e-04, + 9.03936460960799980377e-05, + 7.71980988618959664254e-05, + 6.39721211855788279756e-05, + 5.07233015529098420324e-05, + 3.74592336431094660547e-05, + 2.41875119832061500670e-05, + 1.09157276060909018059e-05, +-2.34853628469845146187e-06, +-1.55977086414162786562e-05, +-2.88242348869596923613e-05, +-4.20205812159120831802e-05, +-5.51792388792400324794e-05, +-6.82927284502260999177e-05, +-8.13536040692178018903e-05, +-9.43544576647877523837e-05, +-1.07287923148899612901e-04, +-1.20146680583802623705e-04, +-1.32923460318065689029e-04, +-1.45611047089732014966e-04, +-1.58202284094046845058e-04, +-1.70690077013562770646e-04, +-1.83067398008342023790e-04, +-1.95327289664015750449e-04, +-2.07462868895485753841e-04, +-2.19467330804082712487e-04, +-2.31333952486024421909e-04, +-2.43056096790058889963e-04, +-2.54627216022116969682e-04, +-2.66040855595085605489e-04, +-2.77290657621565787404e-04, +-2.88370364447411301270e-04, +-2.99273822124557198864e-04, +-3.09994983820817795236e-04, +-3.20527913164946520654e-04, +-3.30866787525005792182e-04, +-3.41005901218438382556e-04, +-3.50939668651816677209e-04, +-3.60662627388737895996e-04, +-3.70169441144112937835e-04, +-3.79454902703223032924e-04, +-3.88513936763931614412e-04, +-3.97341602700649319281e-04, +-4.05933097248160023023e-04, +-4.14283757104453339952e-04, +-4.22389061450620915700e-04, +-4.30244634386746675411e-04, +-4.37846247282407585646e-04, +-4.45189821040535387009e-04, +-4.52271428273436375180e-04, +-4.59087295389815042927e-04, +-4.65633804591701605784e-04, +-4.71907495780237373154e-04, +-4.77905068369312367293e-04, +-4.83623383006156549232e-04, +-4.89059463197895642403e-04, +-4.94210496843377989837e-04, +-4.99073837669386272294e-04, +-5.03647006570560255671e-04, +-5.07927692852353862910e-04, +-5.11913755376417790866e-04, +-5.15603223607854132746e-04, +-5.18994298563852079348e-04, +-5.22085353663235022734e-04, +-5.24874935476607245785e-04, +-5.27361764376676599858e-04, +-5.29544735088589781265e-04, +-5.31422917139951151225e-04, +-5.32995555210500379477e-04, +-5.34262069381259826692e-04, +-5.35222055283147762558e-04, +-5.35875284145083223553e-04, +-5.36221702741643767819e-04, +-5.36261433240417940797e-04, +-5.35994772949250210085e-04, +-5.35422193963616460319e-04, +-5.34544342714442298307e-04, +-5.33362039416725316164e-04, +-5.31876277419383609174e-04, +-5.30088222456788840664e-04, +-5.27999211802546121117e-04, +-5.25610753326072018335e-04, +-5.22924524452632929344e-04, +-5.19942371027533258195e-04, +-5.16666306085201390737e-04, +-5.13098508523981305419e-04, +-5.09241321687478316720e-04, +-5.05097251853375752567e-04, +-5.00668966630677097357e-04, +-4.95959293266389714822e-04, +-4.90971216862717439386e-04, +-4.85707878505841088215e-04, +-4.80172573307527546498e-04, +-4.74368748360683557905e-04, +-4.68300000610171580050e-04, +-4.61970074640185440762e-04, +-4.55382860379525326953e-04, +-4.48542390726171106338e-04, +-4.41452839092643458969e-04, +-4.34118516873516094388e-04, +-4.26543870836773282920e-04, +-4.18733480440457346301e-04, +-4.10692055076295619871e-04, +-4.02424431241824444132e-04, +-3.93935569642999588221e-04, +-3.85230552228620710866e-04, +-3.76314579158696684014e-04, +-3.67192965708273077411e-04, +-3.57871139108791979765e-04, +-3.48354635328699147479e-04, +-3.38649095795268096840e-04, +-3.28760264059559039092e-04, +-3.18693982406488616858e-04, +-3.08456188411998706057e-04, +-2.98052911449364968648e-04, +-2.87490269146621982028e-04, +-2.76774463797361711895e-04, +-2.65911778726769776858e-04, +-2.54908574615198501266e-04, +-2.43771285781356852364e-04, +-2.32506416427293309719e-04, +-2.21120536847362134797e-04, +-2.09620279603374160817e-04, +-1.98012335668160057052e-04, +-1.86303450539779524029e-04, +-1.74500420328618278693e-04, +-1.62610087819718690657e-04, +-1.50639338512448478849e-04, +-1.38595096639894068595e-04, +-1.26484321170500490497e-04, +-1.14314001793776732867e-04, +-1.02091154892787922296e-04, +-8.98228195055708475902e-05, +-7.75160532779040826849e-05, +-6.51779284095440432020e-05, +-5.28155275965366106071e-05, +-4.04359399717151504088e-05, +-2.80462570457926562079e-05, +-1.56535686513557642486e-05, +-3.26495889210444343624e-06, + 9.11249790054165639743e-06, + 2.14717412006368892899e-05, + 3.38057283092167403242e-05, + 4.61074383610954739352e-05, + 5.83698763150761234034e-05, + 7.05860769251900996464e-05, + 8.27491086907310743719e-05, + 9.48520777828465352357e-05, + 1.06888131945465347230e-04, + 1.18850464368359115953e-04, + 1.30732317530151336904e-04, + 1.42526987009093485245e-04, + 1.54227825259548495572e-04, + 1.65828245351846937858e-04, + 1.77321724673696056200e-04, + 1.88701808590856294186e-04, + 1.99962114065118143997e-04, + 2.11096333227541019164e-04, + 2.22098236904959408719e-04, + 2.32961678097786452921e-04, + 2.43680595407194330610e-04, + 2.54249016409682922994e-04, + 2.64661060977358164950e-04, + 2.74910944541823074223e-04, + 2.84992981300038268795e-04, + 2.94901587360451048966e-04, + 3.04631283827309126255e-04, + 3.14176699821949083694e-04, + 3.23532575438972966244e-04, + 3.32693764636005074025e-04, + 3.41655238055194434080e-04, + 3.50412085775090025464e-04, + 3.58959519991325229707e-04, + 3.67292877624660627292e-04, + 3.75407622854972045263e-04, + 3.83299349579812611254e-04, + 3.90963783796212480549e-04, + 3.98396785904493201929e-04, + 4.05594352932717237652e-04, + 4.12552620680778098922e-04, + 4.19267865782840679426e-04, + 4.25736507687102228546e-04, + 4.31955110551815945567e-04, + 4.37920385056580596227e-04, + 4.43629190127953329428e-04, + 4.49078534578485372587e-04, + 4.54265578658337963736e-04, + 4.59187635518681089644e-04, + 4.63842172586124870497e-04, + 4.68226812847528570376e-04, + 4.72339336044462119145e-04, + 4.76177679776842175188e-04, + 4.79739940515123866431e-04, + 4.83024374520600813590e-04, + 4.86029398673382302676e-04, + 4.88753591207665154424e-04, + 4.91195692353966193756e-04, + 4.93354604888095117816e-04, + 4.95229394586578497428e-04, + 4.96819290588439285358e-04, + 4.98123685663175381003e-04, + 4.99142136384935733613e-04, + 4.99874363212820149900e-04, + 5.00320250477433235529e-04, + 5.00479846273746572204e-04, + 5.00353362260458648866e-04, + 4.99941173366037620342e-04, + 4.99243817401748952133e-04, + 4.98261994581954289173e-04, + 4.96996566952077824426e-04, + 4.95448557724650537858e-04, + 4.93619150523917594661e-04, + 4.91509688539529211379e-04, + 4.89121673589913252660e-04, + 4.86456765095920123584e-04, + 4.83516778965485997076e-04, + 4.80303686389979968101e-04, + 4.76819612553058206749e-04, + 4.73066835252845254919e-04, + 4.69047783438315086732e-04, + 4.64765035660812749103e-04, + 4.60221318441676426666e-04, + 4.55419504556999951966e-04, + 4.50362611240582178668e-04, + 4.45053798306218380970e-04, + 4.39496366190426988700e-04, + 4.33693753916839246001e-04, + 4.27649536983611762604e-04, + 4.21367425174935209421e-04, + 4.14851260298147500507e-04, + 4.08105013847745185657e-04, + 4.01132784597763502807e-04, + 3.93938796123864838888e-04, + 3.86527394256778707507e-04, + 3.78903044468504332596e-04, + 3.71070329192896123955e-04, + 3.63033945082216335121e-04, + 3.54798700201316714441e-04, + 3.46369511160995113223e-04, + 3.37751400192573319938e-04, + 3.28949492164903488020e-04, + 3.19969011546054665687e-04, + 3.10815279311211242839e-04, + 3.01493709798685276691e-04, + 2.92009807515892561881e-04, + 2.82369163897162314333e-04, + 2.72577454015293597824e-04, + 2.62640433248783711044e-04, + 2.52563933906683622723e-04, + 2.42353861813065601894e-04, + 2.32016192853029426611e-04, + 2.21556969482438587647e-04, + 2.10982297203188133052e-04, + 2.00298341006229532702e-04, + 1.89511321784351343799e-04, + 1.78627512716812605594e-04, + 1.67653235627924536433e-04, + 1.56594857321689550278e-04, + 1.45458785894609618538e-04, + 1.34251467028869596798e-04, + 1.22979380267843285647e-04, + 1.11649035276331349935e-04, + 1.00266968087514806969e-04, + 8.88397373387060364193e-05, + 7.73739204984463118959e-05, + 6.58761100865689746284e-05, + 5.43529098898822812845e-05, + 4.28109311752722368678e-05, + 3.12567889026958147750e-05, + 1.96970979400246795697e-05, + 8.13846928198325526361e-06, +-3.41249372467339250558e-06, +-1.49491991475911624329e-05, +-2.64650702247123145554e-05, +-3.79535491074849259605e-05, +-4.94081005893409459882e-05, +-6.08222158171220890705e-05, +-7.21894159836215413640e-05, +-8.35032559989468706153e-05, +-9.47573281387071252556e-05, +-1.05945265666950816461e-04, +-1.17060746431808460001e-04, +-1.28097496431813168485e-04, +-1.39049293350893167628e-04, +-1.49909970060043025702e-04, +-1.60673418083712545501e-04, +-1.71333591028951604061e-04, +-1.81884507975470710237e-04, +-1.92320256824521286943e-04, +-2.02634997604990462535e-04, +-2.12822965734663506043e-04, +-2.22878475234921188562e-04, +-2.32795921897065518930e-04, +-2.42569786398529724757e-04, +-2.52194637367171917153e-04, +-2.61665134392132306407e-04, +-2.70976030979354039815e-04, +-2.80122177450312201570e-04, +-2.89098523782284854127e-04, +-2.97900122388595328931e-04, +-3.06522130837423188374e-04, +-3.14959814507391293315e-04, +-3.23208549178839786662e-04, +-3.31263823559207256243e-04, +-3.39121241741069823911e-04, +-3.46776525591634588071e-04, +-3.54225517072336341072e-04, +-3.61464180487291921601e-04, +-3.68488604659406027153e-04, +-3.75295005032959282966e-04, +-3.81879725701552677659e-04, +-3.88239241360328717068e-04, +-3.94370159181469716065e-04, +-4.00269220611873847385e-04, +-4.05933303092217750898e-04, +-4.11359421696386878559e-04, +-4.16544730690475114351e-04, +-4.21486525010528862399e-04, +-4.26182241658291949011e-04, +-4.30629461014228067349e-04, +-4.34825908067166936634e-04, +-4.38769453559957806933e-04, +-4.42458115050543214063e-04, +-4.45890057887998378632e-04, +-4.49063596103017892164e-04, +-4.51977193212385814410e-04, +-4.54629462937196024159e-04, +-4.57019169834384534831e-04, +-4.59145229841358777558e-04, +-4.61006710733478388374e-04, +-4.62602832494264496789e-04, +-4.63932967598159218692e-04, +-4.64996641205815024796e-04, +-4.65793531271870616534e-04, +-4.66323468565258629059e-04, +-4.66586436602117857111e-04, +-4.66582571491450407916e-04, +-4.66312161693693675614e-04, +-4.65775647692456124232e-04, +-4.64973621579678497197e-04, +-4.63906826554567289656e-04, +-4.62576156336664179227e-04, +-4.60982654493493390190e-04, +-4.59127513683252981222e-04, +-4.57012074813076816290e-04, +-4.54637826113443851636e-04, +-4.52006402129344277314e-04, +-4.49119582628882253825e-04, +-4.45979291430018782647e-04, +-4.42587595146185029237e-04, +-4.38946701851662950556e-04, +-4.35058959667485500768e-04, +-4.30926855268744430933e-04, +-4.26553012314354973531e-04, +-4.21940189800147375659e-04, +-4.17091280336356255796e-04, +-4.12009308350574096971e-04, +-4.06697428217259312686e-04, +-4.01158922314968034977e-04, +-3.95397199012481159307e-04, +-3.89415790585079821338e-04, +-3.83218351062148158623e-04, +-3.76808654007610018769e-04, +-3.70190590234281159936e-04, +-3.63368165453703019507e-04, +-3.56345497862799480068e-04, +-3.49126815668818354065e-04, +-3.41716454554033186291e-04, +-3.34118855081727756696e-04, +-3.26338560045002091647e-04, +-3.18380211759965842631e-04, +-3.10248549305032668161e-04, +-3.01948405707699765559e-04, +-2.93484705080720911091e-04, +-2.84862459709394287826e-04, +-2.76086767091391477574e-04, +-2.67162806931154044997e-04, +-2.58095838090502502794e-04, +-2.48891195497272449746e-04, +-2.39554287013787821662e-04, +-2.30090590267009276020e-04, +-2.20505649442205787147e-04, +-2.10805072042026829309e-04, +-2.00994525612865481291e-04, +-1.91079734440417233063e-04, +-1.81066476216359793653e-04, +-1.70960578678090068449e-04, +-1.60767916223468677233e-04, +-1.50494406502535882537e-04, +-1.40146006988172149195e-04, +-1.29728711527686151094e-04, +-1.19248546877326160043e-04, +-1.08711569221710101099e-04, +-9.81238606801850763708e-05, +-8.74915258021262919313e-05, +-7.68206880531919903462e-05, +-6.61174862945537560044e-05, +-5.53880712571479811158e-05, +-4.46386020128183616507e-05, +-3.38752424447514053707e-05, +-2.31041577187158825475e-05, +-1.23315107575055638581e-05, +-1.56345872044351334759e-06, + 9.19385051001696058297e-06, + 1.99342818325943639068e-05, + 3.06517164204148291097e-05, + 4.13400552010434981019e-05, + 5.19932223217173526989e-05, + 6.26051685973046974495e-05, + 7.31698749393950269174e-05, + 8.36813557645763278318e-05, + 9.41336623796225205937e-05, + 1.04520886342181746720e-04, + 1.14837162794693847952e-04, + 1.25076673769810187576e-04, + 1.35233651465430277944e-04, + 1.45302381487516881669e-04, + 1.55277206058868723132e-04, + 1.65152527192051468401e-04, + 1.74922809824715685349e-04, + 1.84582584915542787917e-04, + 1.94126452499097224393e-04, + 2.03549084697879242812e-04, + 2.12845228689902707473e-04, + 2.22009709630148407153e-04, + 2.31037433524272298050e-04, + 2.39923390052979132632e-04, + 2.48662655345496428575e-04, + 2.57250394700618317985e-04, + 2.65681865253823213443e-04, + 2.73952418588994082733e-04, + 2.82057503293309968541e-04, + 2.89992667453910593113e-04, + 2.97753561094963236852e-04, + 3.05335938553796587460e-04, + 3.12735660794901402029e-04, + 3.19948697660284706902e-04, + 3.26971130055313046695e-04, + 3.33799152068596993118e-04, + 3.40429073024882096823e-04, + 3.46857319469846304971e-04, + 3.53080437085642826617e-04, + 3.59095092536410422437e-04, + 3.64898075242447582529e-04, + 3.70486299082366027022e-04, + 3.75856804022209637847e-04, + 3.81006757670713364344e-04, + 3.85933456759954328450e-04, + 3.90634328550441736316e-04, + 3.95106932160183021464e-04, + 3.99348959816850238372e-04, + 4.03358238032495769118e-04, + 4.07132728700219297200e-04, + 4.10670530112230828569e-04, + 4.13969877898831897789e-04, + 4.17029145887845879240e-04, + 4.19846846884104163249e-04, + 4.22421633368623200468e-04, + 4.24752298117164013222e-04, + 4.26837774737901984833e-04, + 4.28677138127993610176e-04, + 4.30269604848864133020e-04, + 4.31614533420087809028e-04, + 4.32711424531789182885e-04, + 4.33559921175517891476e-04, + 4.34159808693626808693e-04, + 4.34511014747204218304e-04, + 4.34613609202668001435e-04, + 4.34467803937177638515e-04, + 4.34073952563060591527e-04, + 4.33432550071505902529e-04, + 4.32544232395796221600e-04, + 4.31409775894451988712e-04, + 4.30030096754630268997e-04, + 4.28406250316232413682e-04, + 4.26539430317180844748e-04, + 4.24430968060405871753e-04, + 4.22082331503046044325e-04, + 4.19495124268545250320e-04, + 4.16671084582238100344e-04, + 4.13612084131137220516e-04, + 4.10320126848655590979e-04, + 4.06797347625035990524e-04, + 4.03046010944322816681e-04, + 3.99068509448671923049e-04, + 3.94867362431040608978e-04, + 3.90445214257016648927e-04, + 3.85804832716899566078e-04, + 3.80949107308997192770e-04, + 3.75881047455209468464e-04, + 3.70603780649984598967e-04, + 3.65120550543784417111e-04, + 3.59434714962230262691e-04, + 3.53549743862119564622e-04, + 3.47469217225564457226e-04, + 3.41196822893517369337e-04, + 3.34736354339987610389e-04, + 3.28091708388290057355e-04, + 3.21266882870694259894e-04, + 3.14265974232871717151e-04, + 3.07093175084575183576e-04, + 2.99752771698005490968e-04, + 2.92249141455357803153e-04, + 2.84586750247056946388e-04, + 2.76770149822231086197e-04, + 2.68803975092983104406e-04, + 2.60692941394056651970e-04, + 2.52441841699531203946e-04, + 2.44055543798067387786e-04, + 2.35538987428655314377e-04, + 2.26897181378157982660e-04, + 2.18135200542623168421e-04, + 2.09258182954089169475e-04, + 2.00271326774336208163e-04, + 1.91179887257744631369e-04, + 1.81989173684729625387e-04, + 1.72704546267654705490e-04, + 1.63331413031008576943e-04, + 1.53875226667652081989e-04, + 1.44341481372964688425e-04, + 1.34735709658744315766e-04, + 1.25063479148570258709e-04, + 1.15330389356819486019e-04, + 1.05542068452749301325e-04, + 9.57041700118449787478e-05, + 8.58223697561741577077e-05, + 7.59023622856443207175e-05, + 6.59498578020433471767e-05, + 5.59705788277444033440e-05, + 4.59702569209572621425e-05, + 3.59546293894085665843e-05, + 2.59294360043086512160e-05, + 1.59004157166498285290e-05, + 5.87330337721188446920e-06, +-4.14617353701999446564e-06, +-1.41522981889934754151e-05, +-2.41393676379234885633e-05, +-3.41016960841382575317e-05, +-4.40336181005696522257e-05, +-5.39294918490548975433e-05, +-6.37837022796263207513e-05, +-7.35906643109786139231e-05, +-8.33448259903158111123e-05, +-9.30406716307915674464e-05, +-1.02672724924753142484e-04, +-1.12235552031169472749e-04, +-1.21723764635187306645e-04, +-1.31132022978417295961e-04, +-1.40455038858246640358e-04, +-1.49687578594178148693e-04, +-1.58824465959857513524e-04, +-1.67860585079007983188e-04, +-1.76790883283683004619e-04, +-1.85610373933242124578e-04, +-1.94314139192479492721e-04, +-2.02897332767363176810e-04, +-2.11355182596845939808e-04, +-2.19682993499378809155e-04, +-2.27876149772357342645e-04, +-2.35930117743474312237e-04, +-2.43840448272265441099e-04, +-2.51602779200596157229e-04, +-2.59212837750722130490e-04, +-2.66666442869611193447e-04, +-2.73959507518241514052e-04, +-2.81088040904634635809e-04, +-2.88048150659414798139e-04, +-2.94836044952623201488e-04, +-3.01448034550882504670e-04, +-3.07880534813461108779e-04, +-3.14130067626494494971e-04, +-3.20193263274004568698e-04, +-3.26066862245033475126e-04, +-3.31747716975704792786e-04, +-3.37232793525372445079e-04, +-3.42519173185958092365e-04, +-3.47604054023637506869e-04, +-3.52484752352054538874e-04, +-3.57158704136308719976e-04, +-3.61623466326981902238e-04, +-3.65876718123521590606e-04, +-3.69916262166333537249e-04, +-3.73740025656983437721e-04, +-3.77346061405942046450e-04, +-3.80732548807360233426e-04, +-3.83897794740389560527e-04, +-3.86840234396619738182e-04, +-3.89558432033239830650e-04, +-3.92051081651568350539e-04, +-3.94317007600659507997e-04, +-3.96355165105705619343e-04, +-3.98164640721032441449e-04, +-3.99744652707502629626e-04, +-4.01094551334191251613e-04, +-4.02213819104267004522e-04, +-4.03102070904986001763e-04, +-4.03759054081854400035e-04, +-4.04184648436960245865e-04, +-4.04378866151571740410e-04, +-4.04341851633132352058e-04, +-4.04073881286819201839e-04, +-4.03575363211878201074e-04, +-4.02846836823000703422e-04, +-4.01888972397027575446e-04, +-4.00702570545332346658e-04, +-3.99288561612268872933e-04, +-3.97648005000088408580e-04, +-3.95782088420835174210e-04, +-3.93692127075682019467e-04, +-3.91379562762282434078e-04, +-3.88845962910724810089e-04, +-3.86093019548719798301e-04, +-3.83122548196679628581e-04, +-3.79936486693416947905e-04, +-3.76536893953195608929e-04, +-3.72925948654929972394e-04, +-3.69105947864348422904e-04, +-3.65079305589995940784e-04, +-3.60848551273959680056e-04, +-3.56416328218264332091e-04, +-3.51785391947902702746e-04, +-3.46958608511509539966e-04, +-3.41938952720719716982e-04, +-3.36729506329282559166e-04, +-3.31333456153044218079e-04, +-3.25754092131937047095e-04, +-3.19994805335147892728e-04, +-3.14059085910667681873e-04, +-3.07950520980461819095e-04, +-3.01672792482518580589e-04, +-2.95229674961088311026e-04, +-2.88625033306340523283e-04, +-2.81862820445018204176e-04, +-2.74947074983157644778e-04, +-2.67881918802505628041e-04, +-2.60671554611964777660e-04, +-2.53320263455520278562e-04, +-2.45832402178220821125e-04, +-2.38212400851451575621e-04, +-2.30464760159363048859e-04, +-2.22594048747734558165e-04, +-2.14604900536931233329e-04, +-2.06502012000535557258e-04, +-1.98290139411133950476e-04, +-1.89974096055152907262e-04, +-1.81558749417992085131e-04, +-1.73049018341384308823e-04, +-1.64449870154523194316e-04, +-1.55766317780646929318e-04, +-1.47003416820761271481e-04, +-1.38166262616194393661e-04, +-1.29259987291687318631e-04, +-1.20289756780731966232e-04, +-1.11260767834878675090e-04, +-1.02178245018739763763e-04, +-9.30474376924268498914e-05, +-8.38736169831565017523e-05, +-7.46620727477739890053e-05, +-6.54181105279376081448e-05, +-5.61470484997162090244e-05, +-4.68542144193485576007e-05, +-3.75449425669173780990e-05, +-2.82245706896867571811e-05, +-1.88984369468525752515e-05, +-9.57187685745089512619e-06, +-2.50220253166946479370e-07, + 9.06121176221840221013e-06, + 1.83571098449908816895e-05, + 2.76321794336816537255e-05, + 3.68811437592135666556e-05, + 4.60987468417495339684e-05, + 5.52797564722329147621e-05, + 6.44189671769343854841e-05, + 7.35112031636342259672e-05, + 8.25513212473374231003e-05, + 9.15342137542006137590e-05, + 1.00454811401901069581e-04, + 1.09308086154850524381e-04, + 1.18089054052647829071e-04, + 1.26792778010161884652e-04, + 1.35414370587798690198e-04, + 1.43948996730092746744e-04, + 1.52391876471503188604e-04, + 1.60738287607595838752e-04, + 1.68983568330243670531e-04, + 1.77123119825359898573e-04, + 1.85152408831718565856e-04, + 1.93066970159443514676e-04, + 2.00862409166768096517e-04, + 2.08534404193699878438e-04, + 2.16078708951240975071e-04, + 2.23491154864851335540e-04, + 2.30767653370864866047e-04, + 2.37904198164594560738e-04, + 2.44896867398899378224e-04, + 2.51741825832007637496e-04, + 2.58435326923423880699e-04, + 2.64973714876783311267e-04, + 2.71353426628539464403e-04, + 2.77570993781410069266e-04, + 2.83623044481539374282e-04, + 2.89506305238360116608e-04, + 2.95217602686185913181e-04, + 3.00753865286583336493e-04, + 3.06112124970612023683e-04, + 3.11289518720129045667e-04, + 3.16283290087134808400e-04, + 3.21090790650627329848e-04, + 3.25709481409937177433e-04, + 3.30136934114071980105e-04, + 3.34370832526131541752e-04, + 3.38408973622323120626e-04, + 3.42249268724889273759e-04, + 3.45889744568388601224e-04, + 3.49328544298793523294e-04, + 3.52563928404906736999e-04, + 3.55594275581636054019e-04, + 3.58418083524750480211e-04, + 3.61033969656628290525e-04, + 3.63440671782813055999e-04, + 3.65637048678958849739e-04, + 3.67622080607960151355e-04, + 3.69394869767037141092e-04, + 3.70954640664598411879e-04, + 3.72300740426744327174e-04, + 3.73432639033317674820e-04, + 3.74349929483439925783e-04, + 3.75052327890526104696e-04, + 3.75539673506779519020e-04, + 3.75811928677284036969e-04, + 3.75869178723718091930e-04, + 3.75711631757917824750e-04, + 3.75339618425418329768e-04, + 3.74753591579224973156e-04, + 3.73954125884068270050e-04, + 3.72941917351453974382e-04, + 3.71717782805840797795e-04, + 3.70282659282345936666e-04, + 3.68637603356378044158e-04, + 3.66783790405674587840e-04, + 3.64722513805233164354e-04, + 3.62455184055677408564e-04, + 3.59983327845599923502e-04, + 3.57308587048594551976e-04, + 3.54432717655444305162e-04, + 3.51357588642338164626e-04, + 3.48085180775715128960e-04, + 3.44617585354531092562e-04, + 3.40957002890739319448e-04, + 3.37105741728795874762e-04, + 3.33066216605056779430e-04, + 3.28840947147959132123e-04, + 3.24432556319903108322e-04, + 3.19843768801808070543e-04, + 3.15077409321264686852e-04, + 3.10136400925462669617e-04, + 3.05023763199732222788e-04, + 2.99742610432934862910e-04, + 2.94296149730754368415e-04, + 2.88687679078032178367e-04, + 2.82920585351309613817e-04, + 2.76998342282779573022e-04, + 2.70924508376842870794e-04, + 2.64702724780600893301e-04, + 2.58336713109347953805e-04, + 2.51830273228646013463e-04, + 2.45187280994006067195e-04, + 2.38411685949818300109e-04, + 2.31507508988586837694e-04, + 2.24478839972069534785e-04, + 2.17329835315641735263e-04, + 2.10064715537319865631e-04, + 2.02687762772885523210e-04, + 1.95203318258571319535e-04, + 1.87615779782783292061e-04, + 1.79929599108352478208e-04, + 1.72149279366823641443e-04, + 1.64279372426300712944e-04, + 1.56324476234388271998e-04, + 1.48289232137772291394e-04, + 1.40178322180001724197e-04, + 1.31996466379041452969e-04, + 1.23748419986174359531e-04, + 1.15438970727843310919e-04, + 1.07072936032028641199e-04, + 9.86551602407646912674e-05, + 9.01905118104061922493e-05, + 8.16838805012586526922e-05, + 7.31401745581928999611e-05, + 6.45643178838649969007e-05, + 5.59612472061890399498e-05, + 4.73359092415654616050e-05, + 3.86932578557977460893e-05, + 3.00382512239181022112e-05, + 2.13758489908508619718e-05, + 1.27110094344164514346e-05, + 4.04868663231493498654e-06, +-4.60617236531486804862e-06, +-1.32486303560268950814e-05, +-2.18737627965935988274e-05, +-3.04766606039162663141e-05, +-3.90524329440386771335e-05, +-4.75962100075382721592e-05, +-5.61031457698656416577e-05, +-6.45684207347658160750e-05, +-7.29872446596370569490e-05, +-8.13548592609855323026e-05, +-8.96665408985710283294e-05, +-9.79176032367135154100e-05, +-1.06103399881264301701e-04, +-1.14219326990759500518e-04, +-1.22260825860294306986e-04, +-1.30223385476667787367e-04, +-1.38102545043372279022e-04, +-1.45893896474014590726e-04, +-1.53593086852781251627e-04, +-1.61195820860575358014e-04, +-1.68697863165478154166e-04, +-1.76095040776206332271e-04, +-1.83383245357263575124e-04, +-1.90558435504502971490e-04, +-1.97616638979844499871e-04, +-2.04553954903916496199e-04, +-2.11366555905413412665e-04, +-2.18050690225988521003e-04, +-2.24602683779532712486e-04, +-2.31018942164689760873e-04, +-2.37295952629612913335e-04, +-2.43430285987647672136e-04, +-2.49418598483226250720e-04, +-2.55257633606716517576e-04, +-2.60944223857345624935e-04, +-2.66475292453244793581e-04, +-2.71847854987617462523e-04, +-2.77059021030343338027e-04, +-2.82105995673898740650e-04, +-2.86986081022970918215e-04, +-2.91696677626899613517e-04, +-2.96235285854203533526e-04, +-3.00599507208460371525e-04, +-3.04787045584920001685e-04, +-3.08795708467034170797e-04, +-3.12623408062509989137e-04, +-3.16268162378132073644e-04, +-3.19728096232883450198e-04, +-3.23001442208842737963e-04, +-3.26086541539376013193e-04, +-3.28981844934199483665e-04, +-3.31685913340901627425e-04, +-3.34197418642568527033e-04, +-3.36515144291180958672e-04, +-3.38637985876496302052e-04, +-3.40564951630163302489e-04, +-3.42295162864854200010e-04, +-3.43827854348234302102e-04, +-3.45162374611635318009e-04, +-3.46298186193322516443e-04, +-3.47234865816296292464e-04, +-3.47972104500599249514e-04, +-3.48509707610135627091e-04, +-3.48847594834057013122e-04, +-3.48985800102794084098e-04, +-3.48924471438857429929e-04, +-3.48663870742568846994e-04, +-3.48204373512918418428e-04, +-3.47546468503779780370e-04, +-3.46690757315755763122e-04, +-3.45637953923957387536e-04, +-3.44388884142068690732e-04, +-3.42944485023055438931e-04, +-3.41305804196959756622e-04, +-3.39473999146208769290e-04, +-3.37450336418937347962e-04, +-3.35236190780833392174e-04, +-3.32833044306071442267e-04, +-3.30242485407915102851e-04, +-3.27466207809625300430e-04, +-3.24506009456285323105e-04, +-3.21363791368333459424e-04, +-3.18041556437396186544e-04, +-3.14541408165269157499e-04, +-3.10865549346798478083e-04, +-3.07016280697481171256e-04, +-3.02995999426636253033e-04, +-2.98807197757022834691e-04, +-2.94452461391812403239e-04, +-2.89934467929851976634e-04, +-2.85255985230187464677e-04, +-2.80419869726833046429e-04, +-2.75429064694814387804e-04, +-2.70286598468527671825e-04, +-2.64995582613490349589e-04, +-2.59559210052583209764e-04, +-2.53980753147903693268e-04, +-2.48263561739382960028e-04, +-2.42411061141333119629e-04, +-2.36426750098121530837e-04, +-2.30314198700187072744e-04, +-2.24077046261636817458e-04, +-2.17718999160677065480e-04, +-2.11243828644175747709e-04, +-2.04655368597559766909e-04, +-1.97957513281590559125e-04, +-1.91154215037028974876e-04, +-1.84249481958865466954e-04, +-1.77247375541147338725e-04, +-1.70152008294119155233e-04, +-1.62967541334830558729e-04, +-1.55698181952718529668e-04, +-1.48348181151564014997e-04, +-1.40921831169260738459e-04, +-1.33423462976836989169e-04, +-1.25857443758204442640e-04, +-1.18228174371988047249e-04, +-1.10540086797179302569e-04, +-1.02797641563733886216e-04, +-9.50053251698690202779e-05, +-8.71676474874451848130e-05, +-7.92891391569480421435e-05, +-7.13743489735723545724e-05, +-6.34278412659133373520e-05, +-5.54541932687728470635e-05, +-4.74579924915896622650e-05, +-3.94438340839858202430e-05, +-3.14163182000519927554e-05, +-2.33800473626161515084e-05, +-1.53396238292672757364e-05, +-7.29964696164099043725e-06, + 7.35289400800058785423e-07, + 8.76059956072690135676e-06, + 1.67717085752691440334e-05, + 2.47640548591994233581e-05, + 3.27330927774992179306e-05, + 4.06742952258349121995e-05, + 4.85831561974826067188e-05, + 5.64551933352481954465e-05, + 6.42859504669411802903e-05, + 7.20710001229515570022e-05, + 7.98059460346407204163e-05, + 8.74864256117493171517e-05, + 9.51081123980788522947e-05, + 1.02666718503417308400e-04, + 1.10157997010735983186e-04, + 1.17577744357177826798e-04, + 1.24921802687524364020e-04, + 1.32186062178827283932e-04, + 1.39366463334907178051e-04, + 1.46458999249442900882e-04, + 1.53459717836390693510e-04, + 1.60364724026482917364e-04, + 1.67170181928681389327e-04, + 1.73872316955147449263e-04, + 1.80467417908883949636e-04, + 1.86951839032647022755e-04, + 1.93322002018104301428e-04, + 1.99574397974115166953e-04, + 2.05705589353056221948e-04, + 2.11712211834139661399e-04, + 2.17590976162706123713e-04, + 2.23338669944412427466e-04, + 2.28952159393546036611e-04, + 2.34428391034224761335e-04, + 2.39764393353856245438e-04, + 2.44957278407680664051e-04, + 2.50004243373813900102e-04, + 2.54902572057763023537e-04, + 2.59649636345685814673e-04, + 2.64242897605613895860e-04, + 2.68679908035895302198e-04, + 2.72958311960145715448e-04, + 2.77075847068031439532e-04, + 2.81030345601230668959e-04, + 2.84819735483968607473e-04, + 2.88442041397530505187e-04, + 2.91895385798214199429e-04, + 2.95177989878195508062e-04, + 2.98288174468830185292e-04, + 3.01224360885935828203e-04, + 3.03985071716642170879e-04, + 3.06568931547421675947e-04, + 3.08974667632958628800e-04, + 3.11201110505533425424e-04, + 3.13247194524650732217e-04, + 3.15111958366658898717e-04, + 3.16794545454155058485e-04, + 3.18294204324996645328e-04, + 3.19610288940773337035e-04, + 3.20742258934658165670e-04, + 3.21689679798506877016e-04, + 3.22452223009245763068e-04, + 3.23029666094488715922e-04, + 3.23421892637434677410e-04, + 3.23628892221117367076e-04, + 3.23650760312099662532e-04, + 3.23487698083753741091e-04, + 3.23140012179301756075e-04, + 3.22608114414811391040e-04, + 3.21892521422396742613e-04, + 3.20993854233888264126e-04, + 3.19912837805281418183e-04, + 3.18650300482314343883e-04, + 3.17207173407532596471e-04, + 3.15584489869251980446e-04, + 3.13783384592866167444e-04, + 3.11805092974967040537e-04, + 3.09650950260776226895e-04, + 3.07322390665431383582e-04, + 3.04820946439691672133e-04, + 3.02148246880660359404e-04, + 2.99306017288154683001e-04, + 2.96296077867383965149e-04, + 2.93120342578621461815e-04, + 2.89780817934593706246e-04, + 2.86279601746334145390e-04, + 2.82618881818277357942e-04, + 2.78800934593397952560e-04, + 2.74828123749229578238e-04, + 2.70702898745622138645e-04, + 2.66427793325122298871e-04, + 2.62005423966893218578e-04, + 2.57438488295109720125e-04, + 2.52729763442789332178e-04, + 2.47882104372053313750e-04, + 2.42898442151831685893e-04, + 2.37781782193984719039e-04, + 2.32535202449068816293e-04, + 2.27161851562591142212e-04, + 2.21664946993031298540e-04, + 2.16047773092666164701e-04, + 2.10313679152429068835e-04, + 2.04466077411766494580e-04, + 1.98508441034933119868e-04, + 1.92444302054725852134e-04, + 1.86277249284949120503e-04, + 1.80010926202826978225e-04, + 1.73649028802625680088e-04, + 1.67195303421656588962e-04, + 1.60653544540157914395e-04, + 1.54027592556047951671e-04, + 1.47321331536073504842e-04, + 1.40538686944578018788e-04, + 1.33683623351231527059e-04, + 1.26760142119053490503e-04, + 1.19772279074078399062e-04, + 1.12724102158015825103e-04, + 1.05619709065267838215e-04, + 9.84632248656736166819e-05, + 9.12587996143574470059e-05, + 8.40106059500621168935e-05, + 7.67228366833554533723e-05, + 6.93997023760999396736e-05, + 6.20454289135817277541e-05, + 5.46642550706949160956e-05, + 4.72604300735806080519e-05, + 3.98382111581210927170e-05, + 3.24018611266886229260e-05, + 2.49556459045488985800e-05, + 1.75038320973170900537e-05, + 1.00506845508623119789e-05, + 2.60046391505357440467e-06, +-4.84257578724628453024e-06, +-1.22741895846601957513e-05, +-1.96901439736055691699e-05, +-2.70862193254132534745e-05, +-3.44582122826427863452e-05, +-4.18019381432365520865e-05, +-4.91132332314092313582e-05, +-5.63879572535800466628e-05, +-6.36219956382819091861e-05, +-7.08112618586212363026e-05, +-7.79516997359988795179e-05, +-8.50392857237956806661e-05, +-9.20700311697229486791e-05, +-9.90399845556698052700e-05, +-1.05945233713539423387e-04, +-1.12781908016172197095e-04, +-1.19546180541878292172e-04, +-1.26234270211473149090e-04, +-1.32842443896610563079e-04, +-1.39367018498237036110e-04, +-1.45804362994017441780e-04, +-1.52150900453594729216e-04, +-1.58403110020568740251e-04, +-1.64557528860099149893e-04, +-1.70610754071058763354e-04, +-1.76559444561685330907e-04, +-1.82400322887701021131e-04, +-1.88130177051889265882e-04, +-1.93745862264151107917e-04, +-1.99244302661073536273e-04, +-2.04622492984076230016e-04, +-2.09877500215226739464e-04, +-2.15006465169834002022e-04, +-2.20006604044963781320e-04, +-2.24875209923037860070e-04, +-2.29609654229712996506e-04, +-2.34207388145253733377e-04, +-2.38665943968643126617e-04, +-2.42982936433764040154e-04, +-2.47156063976803242084e-04, +-2.51183109954370624526e-04, +-2.55061943811678553534e-04, +-2.58790522200035065601e-04, +-2.62366890043213652015e-04, +-2.65789181552087544740e-04, +-2.69055621187019552206e-04, +-2.72164524567514133028e-04, +-2.75114299328679378503e-04, +-2.77903445924066144594e-04, +-2.80530558374482365432e-04, +-2.82994324962458426113e-04, +-2.85293528871928667081e-04, +-2.87427048772961131386e-04, +-2.89393859351164052952e-04, +-2.91193031781574363133e-04, +-2.92823734146810019888e-04, +-2.94285231799317132436e-04, +-2.95576887667566815150e-04, +-2.96698162506095247833e-04, +-2.97648615089306386138e-04, +-2.98427902348986473068e-04, +-2.99035779455541356198e-04, +-2.99472099842951298022e-04, +-2.99736815177487569105e-04, +-2.99829975270314748326e-04, +-2.99751727934055112266e-04, +-2.99502318783477473017e-04, +-2.99082090980496079820e-04, +-2.98491484923676638277e-04, +-2.97731037882504939382e-04, +-2.96801383576682481068e-04, +-2.95703251700761983022e-04, +-2.94437467394450386442e-04, +-2.93004950658959568456e-04, +-2.91406715719765864719e-04, +-2.89643870336288734163e-04, +-2.87717615058818976508e-04, +-2.85629242433306474672e-04, +-2.83380136154447051858e-04, +-2.80971770167645455707e-04, +-2.78405707720416845195e-04, +-2.75683600363831927699e-04, +-2.72807186904635450876e-04, +-2.69778292308697948982e-04, +-2.66598826556476689500e-04, +-2.63270783451207898707e-04, +-2.59796239380568065765e-04, +-2.56177352032518543517e-04, +-2.52416359066249054721e-04, +-2.48515576738865041385e-04, +-2.44477398488780056640e-04, +-2.40304293476628925757e-04, +-2.35998805084586303973e-04, +-2.31563549375006809058e-04, +-2.27001213509300385799e-04, +-2.22314554128057417478e-04, +-2.17506395693240964359e-04, +-2.12579628793644199699e-04, +-2.07537208414486720482e-04, +-2.02382152172165928486e-04, +-1.97117538515386705664e-04, +-1.91746504893500153760e-04, +-1.86272245893312135556e-04, +-1.80698011345398386069e-04, +-1.75027104401053194751e-04, +-1.69262879581007170742e-04, +-1.63408740797064619410e-04, +-1.57468139347822794899e-04, +-1.51444571889650255424e-04, +-1.45341578384115073432e-04, +-1.39162740023062326405e-04, +-1.32911677132557424445e-04, +-1.26592047056915218929e-04, +-1.20207542024052590340e-04, +-1.13761886993405384643e-04, +-1.07258837487659783316e-04, +-1.00702177409562164813e-04, +-9.40957168450681270561e-05, +-8.74432898541086471968e-05, +-8.07487522502475194583e-05, +-7.40159793705156095938e-05, +-6.72488638367082234085e-05, +-6.04513133094537063756e-05, +-5.36272482362472248819e-05, +-4.67805995949890251378e-05, +-3.99153066340006816592e-05, +-3.30353146100565781473e-05, +-2.61445725256313035213e-05, +-1.92470308666743191849e-05, +-1.23466393421882220175e-05, +-5.44734462700067394256e-06, + 1.44691189122907742152e-06, + 8.33219635915731991185e-06, + 1.52045846980238205263e-05, + 2.20601648356691710140e-05, + 2.88950389290342959231e-05, + 3.57053255759800123258e-05, + 4.24871620149298346875e-05, + 4.92367063114172048323e-05, + 5.59501395300588034607e-05, + 6.26236678908249482520e-05, + 6.92535249083772849656e-05, + 7.58359735132689484916e-05, + 8.23673081538160148027e-05, + 8.88438568774603065845e-05, + 9.52619833904571407419e-05, + 1.01618089094736445996e-04, + 1.07908615100796547912e-04, + 1.14130044215511548540e-04, + 1.20278902903740668169e-04, + 1.26351763222651335486e-04, + 1.32345244727680633103e-04, + 1.38256016349078191072e-04, + 1.44080798237992946907e-04, + 1.49816363581082602745e-04, + 1.55459540382645440516e-04, + 1.61007213213293658063e-04, + 1.66456324924208517568e-04, + 1.71803878326033914858e-04, + 1.77046937831481864629e-04, + 1.82182631060826721089e-04, + 1.87208150409221387497e-04, + 1.92120754575244299164e-04, + 1.96917770049651416229e-04, + 2.01596592563618655673e-04, + 2.06154688495617809162e-04, + 2.10589596236331749735e-04, + 2.14898927510659952262e-04, + 2.19080368656271521873e-04, + 2.23131681857964108947e-04, + 2.27050706337181441982e-04, + 2.30835359496065032096e-04, + 2.34483638015429345178e-04, + 2.37993618906142247269e-04, + 2.41363460513226320541e-04, + 2.44591403472347386668e-04, + 2.47675771618061590050e-04, + 2.50614972843412405108e-04, + 2.53407499910435565511e-04, + 2.56051931211167507936e-04, + 2.58546931478778998018e-04, + 2.60891252448485638522e-04, + 2.63083733467921166392e-04, + 2.65123302056677822517e-04, + 2.67008974414759331969e-04, + 2.68739855879716155965e-04, + 2.70315141332255878728e-04, + 2.71734115550168267312e-04, + 2.72996153510415167677e-04, + 2.74100720639277955180e-04, + 2.75047373010480411190e-04, + 2.75835757491237044091e-04, + 2.76465611836200725413e-04, + 2.76936764729322759931e-04, + 2.77249135773662686282e-04, + 2.77402735429210095530e-04, + 2.77397664898823418430e-04, + 2.77234115962408846773e-04, + 2.76912370759493020253e-04, + 2.76432801520381165802e-04, + 2.75795870246112379866e-04, + 2.75002128337457571201e-04, + 2.74052216173225097421e-04, + 2.72946862638190302849e-04, + 2.71686884600967171015e-04, + 2.70273186342183185330e-04, + 2.68706758933346897579e-04, + 2.66988679566817544743e-04, + 2.65120110837324977557e-04, + 2.63102299975484803154e-04, + 2.60936578033862389640e-04, + 2.58624359026030797588e-04, + 2.56167139019227189586e-04, + 2.53566495181161690939e-04, + 2.50824084781579728989e-04, + 2.47941644149205875185e-04, + 2.44920987584716133307e-04, + 2.41764006230414186041e-04, + 2.38472666897310341073e-04, + 2.35049010850323818796e-04, + 2.31495152552345612000e-04, + 2.27813278367987374863e-04, + 2.24005645227630785727e-04, + 2.20074579252881860408e-04, + 2.16022474343967573742e-04, + 2.11851790730109416395e-04, + 2.07565053483680750195e-04, + 2.03164850999056984188e-04, + 1.98653833437066455227e-04, + 1.94034711135973993255e-04, + 1.89310252989946878202e-04, + 1.84483284795969022882e-04, + 1.79556687570185045640e-04, + 1.74533395834689777828e-04, + 1.69416395875703968332e-04, + 1.64208723974330704888e-04, + 1.58913464610781706397e-04, + 1.53533748643116163459e-04, + 1.48072751461745600373e-04, + 1.42533691120615488420e-04, + 1.36919826446232244851e-04, + 1.31234455125635378044e-04, + 1.25480911774428335794e-04, + 1.19662565986003067314e-04, + 1.13782820363092171140e-04, + 1.07845108532812357350e-04, + 1.01852893146268084785e-04, + 9.58096638640913071758e-05, + 8.97189353288038125020e-05, + 8.35842451253892703041e-05, + 7.74091517311708171871e-05, + 7.11972324561945549498e-05, + 6.49520813753084395436e-05, + 5.86773072531284785184e-05, + 5.23765314630894333252e-05, + 4.60533859017605735615e-05, + 3.97115108997169615726e-05, + 3.33545531299399012877e-05, + 2.69861635152601212417e-05, + 2.06099951357281601966e-05, + 1.42297011374239464445e-05, + 7.84893264358421670118e-06, + 1.47133666946563786569e-06, +-4.89944595795788563131e-06, +-1.12597826742650033679e-05, +-1.76060512446440944824e-05, +-2.39346418225641322213e-05, +-3.02419589988916038355e-05, +-3.65244238402926538526e-05, +-4.27784759157675114065e-05, +-4.90005753101717809908e-05, +-5.51872046235883968062e-05, +-6.13348709554239443801e-05, +-6.74401078721121943153e-05, +-7.34994773573187349476e-05, +-7.95095717435526355005e-05, +-8.54670156241022589347e-05, +-9.13684677442247916886e-05, +-9.72106228705329827259e-05, +-1.02990213637535249144e-04, +-1.08704012370301582183e-04, +-1.14348832882239030933e-04, +-1.19921532246967561266e-04, +-1.25419012543391523258e-04, +-1.30838222572801670578e-04, +-1.36176159547326554701e-04, +-1.41429870748598893225e-04, +-1.46596455155808636037e-04, +-1.51673065042229072161e-04, +-1.56656907539345593332e-04, +-1.61545246167741111346e-04, +-1.66335402333829893021e-04, +-1.71024756791804714243e-04, +-1.75610751069764359483e-04, +-1.80090888859417295109e-04, +-1.84462737368601463689e-04, +-1.88723928635743296543e-04, +-1.92872160805764557030e-04, +-1.96905199366593993164e-04, +-2.00820878345682555252e-04, +-2.04617101465884017146e-04, +-2.08291843260079455108e-04, +-2.11843150143963964045e-04, +-2.15269141446432097026e-04, +-2.18568010397017243587e-04, +-2.21738025069880467571e-04, +-2.24777529283855221449e-04, +-2.27684943458087584887e-04, +-2.30458765422837560640e-04, +-2.33097571185028482272e-04, +-2.35600015648165144258e-04, +-2.37964833286258476731e-04, +-2.40190838771433997885e-04, +-2.42276927554912959329e-04, +-2.44222076401095133848e-04, +-2.46025343874493635128e-04, +-2.47685870779298261159e-04, +-2.49202880551373695713e-04, +-2.50575679602528446788e-04, +-2.51803657616905742379e-04, +-2.52886287799411761581e-04, +-2.53823127076041447393e-04, +-2.54613816246114423730e-04, +-2.55258080086343225150e-04, +-2.55755727406747662873e-04, +-2.56106651058446010017e-04, +-2.56310827893362850466e-04, +-2.56368318675959138472e-04, +-2.56279267947061176278e-04, +-2.56043903839951736412e-04, +-2.55662537848869153827e-04, +-2.55135564550115290575e-04, +-2.54463461275976690883e-04, +-2.53646787741720056760e-04, +-2.52686185625914012682e-04, +-2.51582378104383988602e-04, +-2.50336169338122934043e-04, +-2.48948443915500688007e-04, +-2.47420166249151312829e-04, +-2.45752379927938354159e-04, +-2.43946207024417992780e-04, +-2.42002847358256754223e-04, +-2.39923577716073371238e-04, +-2.37709751028206703414e-04, +-2.35362795502931025464e-04, +-2.32884213718665853896e-04, +-2.30275581674753719499e-04, +-2.27538547801391219296e-04, +-2.24674831929338742875e-04, +-2.21686224220039661921e-04, +-2.18574584056813192318e-04, +-2.15341838897799910417e-04, +-2.11989983091363462259e-04, +-2.08521076654672306251e-04, +-2.04937244016203435910e-04, +-2.01240672722932391033e-04, +-1.97433612112999371446e-04, +-1.93518371954601639930e-04, +-1.89497321052062165161e-04, +-1.85372885819735596941e-04, +-1.81147548824731936421e-04, +-1.76823847299330738289e-04, +-1.72404371623836980172e-04, +-1.67891763780981287087e-04, +-1.63288715782630906338e-04, +-1.58597968069809712021e-04, +-1.53822307886959517469e-04, +-1.48964567631409072149e-04, +-1.44027623179032189917e-04, +-1.39014392187015984161e-04, +-1.33927832374908250841e-04, +-1.28770939784726684953e-04, +-1.23546747021317972074e-04, +-1.18258321473934703560e-04, +-1.12908763520077224328e-04, +-1.07501204712651167732e-04, +-1.02038805951497883089e-04, +-9.65247556403633775101e-05, +-9.09622678303766927241e-05, +-8.53545803511158610944e-05, +-7.97049529303493834971e-05, +-7.40166653035361572950e-05, +-6.82930153141845771095e-05, +-6.25373170061634808944e-05, +-5.67528987090696620090e-05, +-5.09431011177533815009e-05, +-4.51112753671087087165e-05, +-3.92607811032360062451e-05, +-3.33949845520835634973e-05, +-2.75172565866769451451e-05, +-2.16309707940438413821e-05, +-1.57395015429393948119e-05, +-9.84622205347808669251e-06, +-3.95450246978667291299e-06, + 1.93229206330573338499e-06, + 7.81080331823583281971e-06, + 1.36776818965353001598e-05, + 1.95295891331412940274e-05, + 2.53631989924010254722e-05, + 3.11751999544031924995e-05, + 3.69622968907776241966e-05, + 4.27212129288199275452e-05, + 4.84486913029018664584e-05, + 5.41414971921248957621e-05, + 5.97964195431813658947e-05, + 6.54102728773860912868e-05, + 7.09798990809431715968e-05, + 7.65021691772440931741e-05, + 8.19739850804731076412e-05, + 8.73922813293384121618e-05, + 9.27540268000407564604e-05, + 9.80562263975138116018e-05, + 1.03295922723993288585e-04, + 1.08470197723987624161e-04, + 1.13576174304741347185e-04, + 1.18611017931288513657e-04, + 1.23571938195231626964e-04, + 1.28456190356295279348e-04, + 1.33261076856053907241e-04, + 1.37983948802590338087e-04, + 1.42622207425680382412e-04, + 1.47173305501465306920e-04, + 1.51634748745910018621e-04, + 1.56004097176282787189e-04, + 1.60278966439910032374e-04, + 1.64457029109492771420e-04, + 1.68536015944279398771e-04, + 1.72513717116415843562e-04, + 1.76387983401819222569e-04, + 1.80156727334917880767e-04, + 1.83817924326707803767e-04, + 1.87369613745391966429e-04, + 1.90809899959169668648e-04, + 1.94136953340610880553e-04, + 1.97349011231975375721e-04, + 2.00444378871088047271e-04, + 2.03421430277243321921e-04, + 2.06278609096683117384e-04, + 2.09014429407214987486e-04, + 2.11627476481567565469e-04, + 2.14116407509085294883e-04, + 2.16479952275410651545e-04, + 2.18716913799805800578e-04, + 2.20826168929834235413e-04, + 2.22806668893034610273e-04, + 2.24657439805431047601e-04, + 2.26377583136560162113e-04, + 2.27966276130837073623e-04, + 2.29422772185062839910e-04, + 2.30746401181916479780e-04, + 2.31936569779289853983e-04, + 2.32992761655362052436e-04, + 2.33914537709302807530e-04, + 2.34701536217598021733e-04, + 2.35353472945890507175e-04, + 2.35870141216392695174e-04, + 2.36251411930833043378e-04, + 2.36497233549024313271e-04, + 2.36607632023086867507e-04, + 2.36582710687435922303e-04, + 2.36422650104641229310e-04, + 2.36127707867309972372e-04, + 2.35698218356151145605e-04, + 2.35134592454421556497e-04, + 2.34437317218964954776e-04, + 2.33606955508089235429e-04, + 2.32644145566544174094e-04, + 2.31549600567894977307e-04, + 2.30324108114598991807e-04, + 2.28968529696129264976e-04, + 2.27483800105504667616e-04, + 2.25870926814611687646e-04, + 2.24130989308722247937e-04, + 2.22265138380645918331e-04, + 2.20274595384963348642e-04, + 2.18160651452820167134e-04, + 2.15924666667776987477e-04, + 2.13568069203236673070e-04, + 2.11092354421993914264e-04, + 2.08499083938437130724e-04, + 2.05789884644064712763e-04, + 2.02966447696813575728e-04, + 2.00030527474900313590e-04, + 1.96983940495784002342e-04, + 1.93828564300923292208e-04, + 1.90566336307002704526e-04, + 1.87199252624317116680e-04, + 1.83729366843086441233e-04, + 1.80158788788307001969e-04, + 1.76489683244053914514e-04, + 1.72724268647881387890e-04, + 1.68864815756162396296e-04, + 1.64913646281104273863e-04, + 1.60873131500388584026e-04, + 1.56745690840089552413e-04, + 1.52533790431842698147e-04, + 1.48239941645072722306e-04, + 1.43866699595155821557e-04, + 1.39416661628403223006e-04, + 1.34892465784759241557e-04, + 1.30296789239119602255e-04, + 1.25632346722192602372e-04, + 1.20901888921826961877e-04, + 1.16108200865747232967e-04, + 1.11254100286645201583e-04, + 1.06342435970584441723e-04, + 1.01376086089681932472e-04, + 9.63579565200426416864e-05, + 9.12909791459249860338e-05, + 8.61781101511258242455e-05, + 8.10223282985787361839e-05, + 7.58266331991632841188e-05, + 7.05940435707285904570e-05, + 6.53275954883418709775e-05, + 6.00303406267707601431e-05, + 5.47053444962296712734e-05, + 4.93556846723300390086e-05, + 4.39844490214451387493e-05, + 3.85947339222574980089e-05, + 3.31896424847004075168e-05, + 2.77722827672396915886e-05, + 2.23457659935181742969e-05, + 1.69132047694604267319e-05, + 1.14777113016647637858e-05, + 6.04239561835710224983e-06, + 6.10363793728645020518e-07, +-4.81528382325380808311e-06, +-1.02314543745700456363e-05, +-1.56350642523847494154e-05, +-2.10230408508807413534e-05, +-2.63923243095009231191e-05, +-3.17398692468697033722e-05, +-3.70626464842205185883e-05, +-4.23576447574330595914e-05, +-4.76218724167029767991e-05, +-5.28523591128858801825e-05, +-5.80461574695681123935e-05, +-6.32003447399251964056e-05, +-6.83120244474383017403e-05, +-7.33783280095512028618e-05, +-7.83964163433584703636e-05, +-8.33634814524302451963e-05, +-8.82767479938875655916e-05, +-9.31334748248567243206e-05, +-9.79309565274441714503e-05, +-1.02666524911384672157e-04, +-1.07337550493532478228e-04, +-1.11941443953376520482e-04, +-1.16475657563775984358e-04, +-1.20937686596131455368e-04, +-1.25325070699215711592e-04, +-1.29635395250910385187e-04, +-1.33866292682098157263e-04, +-1.38015443772047713324e-04, +-1.42080578914434722728e-04, +-1.46059479353512834980e-04, +-1.49949978389612786304e-04, +-1.53749962553389324382e-04, +-1.57457372748113794830e-04, +-1.61070205359542604606e-04, +-1.64586513332575895248e-04, +-1.68004407214276350055e-04, +-1.71322056162632199933e-04, +-1.74537688920543577207e-04, +-1.77649594754509306677e-04, +-1.80656124357563160031e-04, +-1.83555690715879498342e-04, +-1.86346769938744346575e-04, +-1.89027902051352861886e-04, +-1.91597691750067656950e-04, +-1.94054809119746906601e-04, +-1.96397990312779409513e-04, +-1.98626038189485975725e-04, +-2.00737822919565348781e-04, +-2.02732282544295099209e-04, +-2.04608423499208415697e-04, +-2.06365321097002875567e-04, +-2.08002119970448036889e-04, +-2.09518034475094608749e-04, +-2.10912349051600370295e-04, +-2.12184418547517878980e-04, +-2.13333668498409933503e-04, +-2.14359595368183043079e-04, +-2.15261766748550323726e-04, +-2.16039821517564244657e-04, +-2.16693469957175179064e-04, +-2.17222493829804320963e-04, +-2.17626746413933055187e-04, +-2.17906152498744288149e-04, +-2.18060708337866669768e-04, +-2.18090481562302831997e-04, +-2.17995611052633665597e-04, +-2.17776306770636030692e-04, +-2.17432849550450564774e-04, +-2.16965590849471163170e-04, +-2.16374952459152508069e-04, +-2.15661426175948502115e-04, +-2.14825573432618965528e-04, +-2.13868024890168464437e-04, +-2.12789479990694880424e-04, +-2.11590706471458399373e-04, +-2.10272539840493795068e-04, +-2.08835882814101080193e-04, +-2.07281704716627822619e-04, +-2.05611040842872101015e-04, +-2.03824991783563389154e-04, +-2.01924722714337458607e-04, +-1.99911462648656409243e-04, +-1.97786503655151527006e-04, +-1.95551200039875640226e-04, +-1.93206967493983087581e-04, +-1.90755282207361699176e-04, +-1.88197679948765912066e-04, +-1.85535755113050746619e-04, +-1.82771159736013454056e-04, +-1.79905602477525801202e-04, +-1.76940847573584393148e-04, +-1.73878713757827938272e-04, +-1.70721073153264649115e-04, +-1.67469850134842302650e-04, +-1.64127020163558210364e-04, +-1.60694608592805399886e-04, +-1.57174689447680583382e-04, +-1.53569384177978999996e-04, +-1.49880860385627755508e-04, +-1.46111330527314676282e-04, +-1.42263050593096474329e-04, +-1.38338318761709250845e-04, +-1.34339474033567067698e-04, +-1.30268894841948973309e-04, +-1.26128997643502378410e-04, +-1.21922235488716284571e-04, +-1.17651096573263047097e-04, +-1.13318102771055339347e-04, +-1.08925808149881126548e-04, +-1.04476797470485840437e-04, +-9.99736846699831026861e-05, +-9.54191113304803323683e-05, +-9.08157451338251561638e-05, +-8.61662783033089883962e-05, +-8.14734260333982814777e-05, +-7.67399249081906023075e-05, +-7.19685313096766739269e-05, +-6.71620198166663929249e-05, +-6.23231815953190427171e-05, +-5.74548227822070198159e-05, +-5.25597628608498169912e-05, +-4.76408330326411294346e-05, +-4.27008745831808004092e-05, +-3.77427372447754268139e-05, +-3.27692775562946159791e-05, +-2.77833572210794834225e-05, +-2.27878414640919380344e-05, +-1.77855973889981053694e-05, +-1.27794923363028358154e-05, +-7.77239224340285758588e-06, +-2.76716000750597664943e-06, + 2.23334614765047225155e-06, + 7.22627430035223622482e-06, + 1.22087804538059595082e-05, + 1.71780301524608407758e-05, + 2.21312000908374962855e-05, + 2.70654797139531880809e-05, + 3.19780728084379127691e-05, + 3.68661990834432147361e-05, + 4.17270957404514982554e-05, + 4.65580190311022323554e-05, + 5.13562458021581016814e-05, + 5.61190750267443480906e-05, + 6.08438293210010258259e-05, + 6.55278564453003783789e-05, + 7.01685307891888973997e-05, + 7.47632548392249471477e-05, + 7.93094606288941272312e-05, + 8.38046111697948801871e-05, + 8.82462018632895745093e-05, + 9.26317618918994384889e-05, + 9.69588555895161487196e-05, + 1.01225083789883730243e-04, + 1.05428085152447302661e-04, + 1.09565537464902931428e-04, + 1.13635158921721518338e-04, + 1.17634709377956067329e-04, + 1.21561991577586462265e-04, + 1.25414852355879225454e-04, + 1.29191183814908515468e-04, + 1.32888924471751327088e-04, + 1.36506060378661892669e-04, + 1.40040626214685270945e-04, + 1.43490706347988396978e-04, + 1.46854435868515841024e-04, + 1.50130001590280805039e-04, + 1.53315643022813413417e-04, + 1.56409653311238074644e-04, + 1.59410380144482617453e-04, + 1.62316226631138655961e-04, + 1.65125652142516246785e-04, + 1.67837173122445686060e-04, + 1.70449363863413175593e-04, + 1.72960857248622345769e-04, + 1.75370345459602272869e-04, + 1.77676580649003228304e-04, + 1.79878375578234217958e-04, + 1.81974604219625616178e-04, + 1.83964202322818494873e-04, + 1.85846167945095638082e-04, + 1.87619561945405119441e-04, + 1.89283508441830545512e-04, + 1.90837195232300557094e-04, + 1.92279874178338393460e-04, + 1.93610861551680866121e-04, + 1.94829538343613950903e-04, + 1.95935350536894948301e-04, + 1.96927809340166344414e-04, + 1.97806491384736336846e-04, + 1.98571038883713909618e-04, + 1.99221159753417060602e-04, + 1.99756627697045236825e-04, + 2.00177282250609553729e-04, + 2.00483028791162594395e-04, + 2.00673838507340500988e-04, + 2.00749748332303471193e-04, + 2.00710860839155866373e-04, + 2.00557344098951099076e-04, + 2.00289431501410645185e-04, + 1.99907421538506638011e-04, + 1.99411677551082736374e-04, + 1.98802627438700833676e-04, + 1.98080763332926219986e-04, + 1.97246641234288935590e-04, + 1.96300880613169869337e-04, + 1.95244163974890567017e-04, + 1.94077236389296096204e-04, + 1.92800904985150346445e-04, + 1.91416038409673633282e-04, + 1.89923566253578820747e-04, + 1.88324478441976569726e-04, + 1.86619824591544307586e-04, + 1.84810713334366470651e-04, + 1.82898311608877559096e-04, + 1.80883843918355590027e-04, + 1.78768591557429662019e-04, + 1.76553891807085754475e-04, + 1.74241137098672801628e-04, + 1.71831774147425040116e-04, + 1.69327303056034789413e-04, + 1.66729276388829827970e-04, + 1.64039298217118011776e-04, + 1.61259023136285878450e-04, + 1.58390155255254730902e-04, + 1.55434447158867309821e-04, + 1.52393698843932419136e-04, + 1.49269756629439789971e-04, + 1.46064512041690788922e-04, + 1.42779900675020699667e-04, + 1.39417901028690864249e-04, + 1.35980533320795114868e-04, + 1.32469858279776427946e-04, + 1.28887975914319409792e-04, + 1.25237024262341641208e-04, + 1.21519178119826532425e-04, + 1.17736647750260424580e-04, + 1.13891677575382762027e-04, + 1.09986544848155620062e-04, + 1.06023558308557749072e-04, + 1.02005056823126766924e-04, + 9.79334080089949563690e-05, + 9.38110068432369283674e-05, + 8.96402742583390368340e-05, + 8.54236557246172082802e-05, + 8.11636198204074375134e-05, + 7.68626567908638934834e-05, + 7.25232770962033334184e-05, + 6.81480099502408253210e-05, + 6.37394018500648417607e-05, + 5.93000150977037791236e-05, + 5.48324263146410183461e-05, + 5.03392249500377099197e-05, + 4.58230117835234620669e-05, + 4.12863974234202202882e-05, + 3.67320008012637997784e-05, + 3.21624476634885960824e-05, + 2.75803690611435845046e-05, + 2.29883998385047982199e-05, + 1.83891771214516705382e-05, + 1.37853388064824855514e-05, + 9.17952205116795011679e-06, + 4.57436176706797238011e-06, +-2.75108842579818438910e-08, +-4.62346999106136241029e-06, +-9.21089638641225220430e-06, +-1.37871791373255400920e-05, +-1.83497170273250301319e-05, +-2.28959200315399970119e-05, +-2.74232107835103849100e-05, +-3.19290260328724777978e-05, +-3.64108180931019818124e-05, +-4.08660562784996536732e-05, +-4.52922283295994015603e-05, +-4.96868418262625327142e-05, +-5.40474255875064181487e-05, +-5.83715310574944550438e-05, +-6.26567336767544860471e-05, +-6.69006342379224212954e-05, +-7.11008602252454944507e-05, +-7.52550671370984356097e-05, +-7.93609397907785223342e-05, +-8.34161936088556751033e-05, +-8.74185758863736857033e-05, +-9.13658670381457783342e-05, +-9.52558818255899069152e-05, +-9.90864705622930764172e-05, +-1.02855520297645628824e-04, +-1.06560955978024466816e-04, +-1.10200741584761408303e-04, +-1.13772881248329986426e-04, +-1.17275420338133038616e-04, +-1.20706446527301793710e-04, +-1.24064090831927222123e-04, +-1.27346528624161774851e-04, +-1.30551980618646957209e-04, +-1.33678713831734421146e-04, +-1.36725042512981202628e-04, +-1.39689329048471762296e-04, +-1.42569984835333479116e-04, +-1.45365471127236698399e-04, +-1.48074299850179806918e-04, +-1.50695034388278933371e-04, +-1.53226290339108047649e-04, +-1.55666736238194213047e-04, +-1.58015094252302533938e-04, +-1.60270140841145748061e-04, +-1.62430707387187727537e-04, +-1.64495680793215953231e-04, +-1.66464004047380415832e-04, +-1.68334676755447923760e-04, +-1.70106755639931378401e-04, +-1.71779355005955645377e-04, +-1.73351647173555225515e-04, +-1.74822862876237544423e-04, +-1.76192291625613234839e-04, +-1.77459282041936094012e-04, +-1.78623242150403258857e-04, +-1.79683639643093680336e-04, +-1.80640002106423656165e-04, +-1.81491917214075620078e-04, +-1.82239032885274609931e-04, +-1.82881057408414176473e-04, +-1.83417759529990343371e-04, +-1.83848968508822530749e-04, +-1.84174574135603265346e-04, +-1.84394526717789769034e-04, +-1.84508837029895376297e-04, +-1.84517576229257786137e-04, +-1.84420875737372863242e-04, +-1.84218927086907938075e-04, +-1.83911981734526851434e-04, +-1.83500350839676173650e-04, +-1.82984405009505745514e-04, +-1.82364574010110863959e-04, +-1.81641346444305146679e-04, +-1.80815269396154251801e-04, +-1.79886948042512636280e-04, +-1.78857045231831964091e-04, +-1.77726281030521376285e-04, +-1.76495432237164907125e-04, +-1.75165331864910952826e-04, +-1.73736868592374774480e-04, +-1.72210986183407241141e-04, +-1.70588682876102914121e-04, +-1.68871010741435372948e-04, +-1.67059075011932430324e-04, +-1.65154033380787864348e-04, +-1.63157095271909268353e-04, +-1.61069521081280296517e-04, +-1.58892621390163224591e-04, +-1.56627756150609387950e-04, +-1.54276333843780973348e-04, +-1.51839810611594959108e-04, +-1.49319689362255997572e-04, +-1.46717518850139323847e-04, +-1.44034892730693565204e-04, +-1.41273448590855218087e-04, +-1.38434866955593221692e-04, +-1.35520870271185604229e-04, +-1.32533221865797814620e-04, +-1.29473724888089073738e-04, +-1.26344221224348324251e-04, +-1.23146590394907499066e-04, +-1.19882748430450496667e-04, +-1.16554646728892494570e-04, +-1.13164270893511021972e-04, +-1.09713639553016026698e-04, +-1.06204803164258788938e-04, +-1.02639842798286093709e-04, +-9.90208689104574309690e-05, +-9.53500200953488063907e-05, +-9.16294618271747146219e-05, +-8.78613851864693950078e-05, +-8.40480055737724741525e-05, +-8.01915614110729224086e-05, +-7.62943128317693849017e-05, +-7.23585403599120898779e-05, +-6.83865435794958062077e-05, +-6.43806397945781601344e-05, +-6.03431626810021750013e-05, +-5.62764609305052045107e-05, +-5.21828968880001095782e-05, +-4.80648451828273766406e-05, +-4.39246913547101223052e-05, +-3.97648304753519063080e-05, +-3.55876657662771198705e-05, +-3.13956072138546100360e-05, +-2.71910701822341436737e-05, +-2.29764740250598643260e-05, +-1.87542406966089186175e-05, +-1.45267933633486321363e-05, +-1.02965550165577958658e-05, +-6.06594708686369126855e-06, +-1.83738806147565725218e-06, + 2.38670789508730654728e-06, + 6.60393231605029799332e-06, + 1.08118838022856526365e-05, + 1.50081693864890804819e-05, + 1.91904058907051211296e-05, + 2.33562212764937420536e-05, + 2.75032559869653701879e-05, + 3.16291642799266015692e-05, + 3.57316155513857358346e-05, + 3.98082956486727347189e-05, + 4.38569081724363369137e-05, + 4.78751757667874686011e-05, + 5.18608413968659121744e-05, + 5.58116696131162758521e-05, + 5.97254478015662288413e-05, + 6.35999874194105038012e-05, + 6.74331252152119678313e-05, + 7.12227244330430300963e-05, + 7.49666759998972407220e-05, + 7.86628996957159043685e-05, + 8.23093453053795327638e-05, + 8.59039937520326019873e-05, + 8.94448582111133600001e-05, + 9.29299852044797151680e-05, + 9.63574556740282402905e-05, + 9.97253860342133961791e-05, + 1.03031929202938195831e-04, + 1.06275275610134644190e-04, + 1.09453654183648506066e-04, + 1.12565333311777745389e-04, + 1.15608621781949924361e-04, + 1.18581869695136337068e-04, + 1.21483469355360853659e-04, + 1.24311856133939833708e-04, + 1.27065509307947152248e-04, + 1.29742952872464735155e-04, + 1.32342756326188934566e-04, + 1.34863535429971070998e-04, + 1.37303952937931089294e-04, + 1.39662719300668973499e-04, + 1.41938593340331764125e-04, + 1.44130382897093850406e-04, + 1.46236945446754414840e-04, + 1.48257188689131702477e-04, + 1.50190071106954631209e-04, + 1.52034602494970392606e-04, + 1.53789844459004473734e-04, + 1.55454910884727745025e-04, + 1.57028968375900465160e-04, + 1.58511236661886526942e-04, + 1.59900988974221943979e-04, + 1.61197552392132844234e-04, + 1.62400308156727989691e-04, + 1.63508691953843704383e-04, + 1.64522194165353128834e-04, + 1.65440360088857943638e-04, + 1.66262790125675229700e-04, + 1.66989139937054223255e-04, + 1.67619120568575667371e-04, + 1.68152498542703266729e-04, + 1.68589095919475644722e-04, + 1.68928790325348127024e-04, + 1.69171514950206333802e-04, + 1.69317258512600938907e-04, + 1.69366065193253035638e-04, + 1.69318034536926169398e-04, + 1.69173321322751827635e-04, + 1.68932135403124315375e-04, + 1.68594741511303550284e-04, + 1.68161459037872361389e-04, + 1.67632661776220571190e-04, + 1.67008777637239416583e-04, + 1.66290288333431385444e-04, + 1.65477729032657161099e-04, + 1.64571687981757684184e-04, + 1.63572806100295385775e-04, + 1.62481776544717680536e-04, + 1.61299344243187993495e-04, + 1.60026305401423106544e-04, + 1.58663506979840374144e-04, + 1.57211846142359855600e-04, + 1.55672269677209203047e-04, + 1.54045773390101885464e-04, + 1.52333401470171580496e-04, + 1.50536245829059009979e-04, + 1.48655445413586417922e-04, + 1.46692185492392439651e-04, + 1.44647696917026745639e-04, + 1.42523255357962074646e-04, + 1.40320180515933701443e-04, + 1.38039835309150310440e-04, + 1.35683625036847225554e-04, + 1.33252996519696450227e-04, + 1.30749437217595669385e-04, + 1.28174474325369749201e-04, + 1.25529673846935238340e-04, + 1.22816639648479919303e-04, + 1.20037012491233243219e-04, + 1.17192469044403129027e-04, + 1.14284720878873418933e-04, + 1.11315513442261188005e-04, + 1.08286625015946468605e-04, + 1.05199865654693577497e-04, + 1.02057076109495512093e-04, + 9.88601267342783304043e-05, + 9.56109163771139760083e-05, + 9.23113712565947120868e-05, + 8.89634438240340108539e-05, + 8.55691116121616991534e-05, + 8.21303760709912982884e-05, + 7.86492613915423208508e-05, + 7.51278133181146123365e-05, + 7.15680979497604612561e-05, + 6.79722005317787153359e-05, + 6.43422242377698607113e-05, + 6.06802889430856936094e-05, + 5.69885299903377532185e-05, + 5.32690969476886882583e-05, + 4.95241523606481209006e-05, + 4.57558704980855863662e-05, + 4.19664360932403064002e-05, + 3.81580430803206248217e-05, + 3.43328933276007924294e-05, + 3.04931953676192458200e-05, + 2.66411631252087834044e-05, + 2.27790146442161646153e-05, + 1.89089708134602095535e-05, + 1.50332540927946444229e-05, + 1.11540872399499682495e-05, + 7.27369203889113503421e-06, + 3.39428803041684083773e-06, +-4.81908754276311450070e-07, +-4.35268705634372629675e-06, +-8.21584164763919663841e-06, +-1.20691745839433958802e-05, +-1.59104964523640528653e-05, +-1.97376276122016780436e-05, +-2.35483994285795049709e-05, +-2.73406554981410021381e-05, +-3.11122528661240456025e-05, +-3.48610632341272955897e-05, +-3.85849741578888450833e-05, +-4.22818902344056668941e-05, +-4.59497342777289552842e-05, +-4.95864484827761740015e-05, +-5.31899955765110986849e-05, +-5.67583599558492673393e-05, +-6.02895488116546415976e-05, +-6.37815932381954160072e-05, +-6.72325493274930760176e-05, +-7.06404992478322041284e-05, +-7.40035523060039669620e-05, +-7.73198459925695190907e-05, +-8.05875470096189763401e-05, +-8.38048522804609266092e-05, +-8.69699899406400548209e-05, +-9.00812203098600702616e-05, +-9.31368368441220313616e-05, +-9.61351670676795016460e-05, +-9.90745734842556015267e-05, +-1.01953454467028386448e-04, +-1.04770245126946709891e-04, +-1.07523418158803123158e-04, +-1.10211484664747875421e-04, +-1.12832994954700652560e-04, +-1.15386539323270961746e-04, +-1.17870748802769852344e-04, +-1.20284295891912211356e-04, +-1.22625895259826191760e-04, +-1.24894304424997594233e-04, +-1.27088324408796619729e-04, +-1.29206800363245279464e-04, +-1.31248622172700554062e-04, +-1.33212725029144128013e-04, +-1.35098089980784487676e-04, +-1.36903744453693149413e-04, +-1.38628762746211502523e-04, +-1.40272266495882424152e-04, +-1.41833425118677113443e-04, +-1.43311456220300168993e-04, +-1.44705625979375639015e-04, +-1.46015249502334635862e-04, +-1.47239691149835216733e-04, +-1.48378364834568840904e-04, +-1.49430734290319368980e-04, +-1.50396313312156941142e-04, +-1.51274665967682871333e-04, +-1.52065406779206268055e-04, +-1.52768200876835928996e-04, +-1.53382764122401261215e-04, +-1.53908863204188484618e-04, +-1.54346315702462519998e-04, +-1.54694990125800718034e-04, +-1.54954805918226855375e-04, +-1.55125733437199472397e-04, +-1.55207793902502094903e-04, +-1.55201059316101394776e-04, +-1.55105652353058453673e-04, +-1.54921746223595071862e-04, +-1.54649564506431944988e-04, +-1.54289380953534071422e-04, +-1.53841519266410082720e-04, +-1.53306352844135500117e-04, +-1.52684304503277075687e-04, +-1.51975846169923051046e-04, +-1.51181498544025521777e-04, +-1.50301830736287767064e-04, +-1.49337459877842251886e-04, +-1.48289050702975444508e-04, +-1.47157315105178143448e-04, +-1.45943011666808031192e-04, +-1.44646945162670226758e-04, +-1.43269966037836245969e-04, +-1.41812969860030777154e-04, +-1.40276896746939125880e-04, +-1.38662730768791489120e-04, +-1.36971499326602120161e-04, +-1.35204272506452450198e-04, +-1.33362162410215011723e-04, +-1.31446322463141056745e-04, +-1.29457946698729233501e-04, +-1.27398269021328599442e-04, +-1.25268562446894228622e-04, +-1.23070138322430765393e-04, +-1.20804345524507650679e-04, +-1.18472569637393813956e-04, +-1.16076232111318126267e-04, +-1.13616789401283968986e-04, +-1.11095732087066782702e-04, +-1.08514583974842290402e-04, +-1.05874901181016539101e-04, +-1.03178271198800118515e-04, +-1.00426311948084758256e-04, +-9.76206708091875252457e-05, +-9.47630236410444991074e-05, +-9.18550737843973141112e-05, +-8.88985510506610496001e-05, +-8.58952106969416680562e-05, +-8.28468323879038561972e-05, +-7.97552191450655496591e-05, +-7.66221962841397250411e-05, +-7.34496103410512394703e-05, +-7.02393279872563352237e-05, +-6.69932349350013444994e-05, +-6.37132348331598941495e-05, +-6.04012481542852742197e-05, +-5.70592110735821189476e-05, +-5.36890743402856300114e-05, +-5.02928021423770289528e-05, +-4.68723709650220007926e-05, +-4.34297684435565900540e-05, +-3.99669922116305890969e-05, +-3.64860487451815660126e-05, +-3.29889522029066755543e-05, +-2.94777232639011821304e-05, +-2.59543879631318446101e-05, +-2.24209765254152845900e-05, +-1.88795221985704670439e-05, +-1.53320600864227232015e-05, +-1.17806259822765688943e-05, +-8.22725520364250435790e-06, +-4.67398142876525914271e-06, +-1.12283553561652046528e-06, + 2.42415555586849744280e-06, + 5.96497003777039182297e-06, + 9.49759236367494958416e-06, + 1.30200143930290886731e-05, + 1.65302365297154976124e-05, + 2.00262688542018995176e-05, + 2.35061322486258601641e-05, + 2.69678595141725338990e-05, + 3.04094964801652475677e-05, + 3.38291031041225136330e-05, + 3.72247545623280811614e-05, + 4.05945423301795488562e-05, + 4.39365752517605946421e-05, + 4.72489805980300616090e-05, + 5.05299051130391751476e-05, + 5.37775160475925401854e-05, + 5.69900021797799109010e-05, + 6.01655748218186950589e-05, + 6.33024688126045798455e-05, + 6.63989434955355209119e-05, + 6.94532836809095877094e-05, + 7.24638005925247566689e-05, + 7.54288327978053365708e-05, + 7.83467471210983574734e-05, + 8.12159395395303644084e-05, + 8.40348360609798490086e-05, + 8.68018935836787020261e-05, + 8.95156007369763171777e-05, + 9.21744787028109000904e-05, + 9.47770820174428766953e-05, + 9.73219993530192951838e-05, + 9.98078542785484291089e-05, + 1.02233305999877626346e-04, + 1.04597050078279252879e-04, + 1.06897819127260571481e-04, + 1.09134383487232477302e-04, + 1.11305551877675454743e-04, + 1.13410172026465080842e-04, + 1.15447131276023696555e-04, + 1.17415357165986388734e-04, + 1.19313817992076323833e-04, + 1.21141523340904152650e-04, + 1.22897524600417128735e-04, + 1.24580915445738179192e-04, + 1.26190832300148298968e-04, + 1.27726454771003749460e-04, + 1.29187006060312931576e-04, + 1.30571753349855405749e-04, + 1.31880008160592337128e-04, + 1.33111126686225034448e-04, + 1.34264510100741093525e-04, + 1.35339604839805301758e-04, + 1.36335902855876962966e-04, + 1.37252941846921911991e-04, + 1.38090305458667854995e-04, + 1.38847623460269244903e-04, + 1.39524571893355508502e-04, + 1.40120873194398874121e-04, + 1.40636296290376592178e-04, + 1.41070656667688923902e-04, + 1.41423816414358241448e-04, + 1.41695684235501812628e-04, + 1.41886215442108465281e-04, + 1.41995411913169058797e-04, + 1.42023322031210527672e-04, + 1.41970040591311803596e-04, + 1.41835708683687403576e-04, + 1.41620513549942957229e-04, + 1.41324688413120390503e-04, + 1.40948512281664279549e-04, + 1.40492309727460512516e-04, + 1.39956450638105661232e-04, + 1.39341349943586742142e-04, + 1.38647467317560966387e-04, + 1.37875306853443076616e-04, + 1.37025416715516460461e-04, + 1.36098388765306077238e-04, + 1.35094858163456845238e-04, + 1.34015502947381628333e-04, + 1.32861043584951986655e-04, + 1.31632242504520034906e-04, + 1.30329903601576123319e-04, + 1.28954871722338328469e-04, + 1.27508032124644551074e-04, + 1.25990309916430414392e-04, + 1.24402669472184333093e-04, + 1.22746113827731657530e-04, + 1.21021684053717931608e-04, + 1.19230458608205958028e-04, + 1.17373552668725822899e-04, + 1.15452117444264388342e-04, + 1.13467339467561269067e-04, + 1.11420439868162524316e-04, + 1.09312673626677319912e-04, + 1.07145328810660439892e-04, + 1.04919725792656324940e-04, + 1.02637216450778944853e-04, + 1.00299183352382616555e-04, + 9.79070389212828459625e-05, + 9.54622245890343021661e-05, + 9.29662099307709859563e-05, + 9.04204917861251337118e-05, + 8.78265933657491361646e-05, + 8.51860633439697795440e-05, + 8.25004749381152567740e-05, + 7.97714249750583101993e-05, + 7.70005329455285302594e-05, + 7.41894400467507647698e-05, + 7.13398082139749418204e-05, + 6.84533191414649809991e-05, + 6.55316732935233309948e-05, + 6.25765889061299349127e-05, + 5.95898009797798930746e-05, + 5.65730602641084840982e-05, + 5.35281322348962640303e-05, + 5.04567960640498228923e-05, + 4.73608435831570034977e-05, + 4.42420782412198123029e-05, + 4.11023140571756856096e-05, + 3.79433745677702796120e-05, + 3.47670917715006306549e-05, + 3.15753050690913554294e-05, + 2.83698602012252819608e-05, + 2.51526081840889388815e-05, + 2.19254042433976171740e-05, + 1.86901067473987712679e-05, + 1.54485761396172072233e-05, + 1.22026738718400676369e-05, + 8.95426133799693216720e-06, + 5.70519880953679468414e-06, + 2.45734437291689684403e-06, +-7.87447130237725029692e-07, +-4.02732515958524032887e-06, +-7.26044452868275316679e-06, +-1.04849664530539972413e-05, +-1.36990595931614081774e-05, +-1.69009010916851591059e-05, +-2.00886776045228981175e-05, +-2.32605863249292218813e-05, +-2.64148360002174825494e-05, +-2.95496479404527710906e-05, +-3.26632570185692985083e-05, +-3.57539126613519710695e-05, +-3.88198798307268989525e-05, +-4.18594399948131874701e-05, +-4.48708920881937505377e-05, +-4.78525534608703297839e-05, +-5.08027608153759224091e-05, +-5.37198711315230623370e-05, +-5.66022625782771395811e-05, +-5.94483354122496957970e-05, +-6.22565128623159649065e-05, +-6.50252419998696961625e-05, +-6.77529945942363268996e-05, +-7.04382679527763058127e-05, +-7.30795857452109842494e-05, +-7.56754988117607863083e-05, +-7.82245859545587472750e-05, +-8.07254547120429588646e-05, +-8.31767421157772956445e-05, +-8.55771154294189502010e-05, +-8.79252728693081722763e-05, +-9.02199443063830727177e-05, +-9.24598919490082272500e-05, +-9.46439110063570436353e-05, +-9.67708303319964480843e-05, +-9.88395130473318793462e-05, +-1.00848857144579225412e-04, +-1.02797796068976429913e-04, +-1.04685299279854606281e-04, +-1.06510372790377650341e-04, +-1.08272059685596318680e-04, +-1.09969440618577611341e-04, +-1.11601634284353844629e-04, +-1.13167797871448837341e-04, +-1.14667127490753893888e-04, +-1.16098858581540945157e-04, +-1.17462266294409572748e-04, +-1.18756665850985608014e-04, +-1.19981412880174577386e-04, +-1.21135903730876983027e-04, +-1.22219575760907419324e-04, +-1.23231907602096356184e-04, +-1.24172419401388892416e-04, +-1.25040673037858960726e-04, +-1.25836272315542666532e-04, +-1.26558863132016492748e-04, +-1.27208133622654898272e-04, +-1.27783814280521123164e-04, +-1.28285678051853307665e-04, +-1.28713540407127574909e-04, +-1.29067259387689078475e-04, +-1.29346735627960067851e-04, +-1.29551912353247712954e-04, +-1.29682775353174970954e-04, +-1.29739352930806405104e-04, +-1.29721715827507011074e-04, +-1.29629977123626777182e-04, +-1.29464292115094922872e-04, +-1.29224858166029714888e-04, +-1.28911914537480141833e-04, +-1.28525742192432532911e-04, +-1.28066663577224341096e-04, +-1.27535042379524224485e-04, +-1.26931283263051979506e-04, +-1.26255831579210470172e-04, +-1.25509173055851516688e-04, +-1.24691833463355639632e-04, +-1.23804378258269496800e-04, +-1.22847412204727150179e-04, +-1.21821578973907172273e-04, +-1.20727560721779606824e-04, +-1.19566077645420637825e-04, +-1.18337887518172143108e-04, +-1.17043785203959168793e-04, +-1.15684602151032309364e-04, +-1.14261205865508758540e-04, +-1.12774499364983135674e-04, +-1.11225420612612888125e-04, +-1.09614941931962398339e-04, +-1.07944069403014051949e-04, +-1.06213842239701207601e-04, +-1.04425332149347485926e-04, +-1.02579642674402744655e-04, +-1.00677908516879591628e-04, +-9.87212948458993696643e-05, +-9.67109965887680804323e-05, +-9.46482377060114694195e-05, +-9.25342704508053923206e-05, +-9.03703746132478017740e-05, +-8.81578567499270010759e-05, +-8.58980493992450127834e-05, +-8.35923102829684219880e-05, +-8.12420214944795825900e-05, +-7.88485886742140853296e-05, +-7.64134401727725140778e-05, +-7.39380262022039087908e-05, +-7.14238179759623244237e-05, +-6.88723068380450985934e-05, +-6.62850033818259808810e-05, +-6.36634365591029851607e-05, +-6.10091527798890391780e-05, +-5.83237150034378014633e-05, +-5.56087018211295729380e-05, +-5.28657065316302825957e-05, +-5.00963362089557252181e-05, +-4.73022107639477868909e-05, +-4.44849619997154997839e-05, +-4.16462326615831018211e-05, +-3.87876754821360727392e-05, +-3.59109522218197118487e-05, +-3.30177327057781363410e-05, +-3.01096938573906879706e-05, +-2.71885187291101264469e-05, +-2.42558955311136346803e-05, +-2.13135166584285751863e-05, +-1.83630777169545625609e-05, +-1.54062765490442216251e-05, +-1.24448122591593738538e-05, +-9.48038424016769929749e-06, +-6.51469120083589183379e-06, +-3.54943019507466532529e-06, +-5.86295653488527638405e-07, + 2.37302158221821148760e-06, + 5.32683522143069861928e-06, + 8.27346448286191381023e-06, + 1.12112350482972268184e-05, + 1.41384800113054187414e-05, + 1.70535408203802065375e-05, + 1.99547682159801403000e-05, + 2.28405231609389523773e-05, + 2.57091777637233010942e-05, + 2.85591161940189065772e-05, + 3.13887355901324983888e-05, + 3.41964469577007317870e-05, + 3.69806760592044563105e-05, + 3.97398642937916670619e-05, + 4.24724695669193537460e-05, + 4.51769671493239000906e-05, + 4.78518505248824157702e-05, + 5.04956322267979359933e-05, + 5.31068446617757945380e-05, + 5.56840409216389250861e-05, + 5.82257955819805972353e-05, + 6.07307054873712566403e-05, + 6.31973905227825399032e-05, + 6.56244943706810369847e-05, + 6.80106852534736013504e-05, + 7.03546566608603151554e-05, + 7.26551280617074665301e-05, + 7.49108456000490471188e-05, + 7.71205827748727728481e-05, + 7.92831411032435707121e-05, + 8.13973507665162628304e-05, + 8.34620712392105025155e-05, + 8.54761919002437216665e-05, + 8.74386326261934136023e-05, + 8.93483443662723540333e-05, + 9.12043096987145523709e-05, + 9.30055433682796324664e-05, + 9.47510928045935062712e-05, + 9.64400386210567564342e-05, + 9.80714950940618610149e-05, + 9.96446106222721028753e-05, + 1.01158568165728382656e-04, + 1.02612585664560169562e-04, + 1.04005916437090132763e-04, + 1.05337849557132784027e-04, + 1.06607710210300974068e-04, + 1.07814860029146553436e-04, + 1.08958697406971076818e-04, + 1.10038657790159221262e-04, + 1.11054213948895991334e-04, + 1.12004876226144938888e-04, + 1.12890192764771252285e-04, + 1.13709749712725811358e-04, + 1.14463171406168479332e-04, + 1.15150120530503418228e-04, + 1.15770298259229445850e-04, + 1.16323444370574466855e-04, + 1.16809337341866760875e-04, + 1.17227794421640891544e-04, + 1.17578671679441387104e-04, + 1.17861864033347977262e-04, + 1.18077305255228525620e-04, + 1.18224967953752292129e-04, + 1.18304863535199995448e-04, + 1.18317042142129913288e-04, + 1.18261592569961779611e-04, + 1.18138642161559509242e-04, + 1.17948356679904758004e-04, + 1.17690940158963789036e-04, + 1.17366634732863803995e-04, + 1.16975720443508680781e-04, + 1.16518515026772340008e-04, + 1.15995373677425865329e-04, + 1.15406688792958039944e-04, + 1.14752889696471350382e-04, + 1.14034442338837080757e-04, + 1.13251848980312161972e-04, + 1.12405647851827392831e-04, + 1.11496412796171015655e-04, + 1.10524752889300383963e-04, + 1.09491312042027578609e-04, + 1.08396768582333136470e-04, + 1.07241834818576963558e-04, + 1.06027256583881440439e-04, + 1.04753812761974128402e-04, + 1.03422314794789343279e-04, + 1.02033606172135439690e-04, + 1.00588561903744460506e-04, + 9.90880879740364323887e-05, + 9.75331207799133901139e-05, + 9.59246265519796495209e-05, + 9.42636007594733522788e-05, + 9.25510674993434647893e-05, + 9.07880788697715116788e-05, + 8.89757143285934223474e-05, + 8.71150800369563193095e-05, + 8.52073081886286283915e-05, + 8.32535563253643403313e-05, + 8.12550066387327429764e-05, + 7.92128652588326546708e-05, + 7.71283615303221291911e-05, + 7.50027472761658441352e-05, + 7.28372960496142743273e-05, + 7.06333023747593316630e-05, + 6.83920809761930819422e-05, + 6.61149659981945323883e-05, + 6.38033102139136647918e-05, + 6.14584842250172271472e-05, + 5.90818756522692805321e-05, + 5.66748883175234417645e-05, + 5.42389414176053005876e-05, + 5.17754686905652722838e-05, + 4.92859175748246270223e-05, + 4.67717483616246192265e-05, + 4.42344333413538523341e-05, + 4.16754559442534589821e-05, + 3.90963098759170062319e-05, + 3.64984982481686095644e-05, + 3.38835327057898264913e-05, + 3.12529325496060770987e-05, + 2.86082238564397440281e-05, + 2.59509385964386121227e-05, + 2.32826137482886975970e-05, + 2.06047904128203539622e-05, + 1.79190129255183850797e-05, + 1.52268279684512867372e-05, + 1.25297836820848089342e-05, + 9.82942877762201860177e-06, + 7.12731165015420239825e-06, + 4.42497949335259697511e-06, + 1.72397741607120027234e-06, +-9.74152438591300545820e-07, +-3.66787177127622279055e-06, +-6.35564700089772787053e-06, +-9.03595013522811150888e-06, +-1.17072596370426850940e-05, +-1.43680612853348429033e-05, +-1.70168490311088741731e-05, +-1.96521258473063757481e-05, +-2.22724045722929874815e-05, +-2.48762087465587318491e-05, +-2.74620734420669071810e-05, +-3.00285460838262985587e-05, +-3.25741872632199556503e-05, +-3.50975715426378017596e-05, +-3.75972882509638620259e-05, +-4.00719422694826037015e-05, +-4.25201548077314798470e-05, +-4.49405641689601653135e-05, +-4.73318265046533437649e-05, +-4.96926165577844057412e-05, +-5.20216283943892467806e-05, +-5.43175761229789356922e-05, +-5.65791946015099025133e-05, +-5.88052401314395777510e-05, +-6.09944911385232351646e-05, +-6.31457488399748983641e-05, +-6.52578378976302012505e-05, +-6.73296070567570273304e-05, +-6.93599297701697614779e-05, +-7.13477048073084426077e-05, +-7.32918568479592438987e-05, +-7.51913370602950043584e-05, +-7.70451236629288198831e-05, +-7.88522224706823078241e-05, +-8.06116674237784532151e-05, +-8.23225211001796784195e-05, +-8.39838752108034195757e-05, +-8.55948510773545134279e-05, +-8.71546000925265052688e-05, +-8.86623041623341395616e-05, +-9.01171761303480768493e-05, +-9.15184601836167176863e-05, +-9.28654322400672107207e-05, +-9.41574003171887131567e-05, +-9.53937048818311668537e-05, +-9.65737191809003779359e-05, +-9.76968495528504664652e-05, +-9.87625357197741252134e-05, +-9.97702510599723062104e-05, +-1.00719502860870411881e-04, +-1.01609832552167786510e-04, +-1.02440815919101530407e-04, +-1.03212063295764626164e-04, +-1.03923219738351186561e-04, +-1.04573965178293452004e-04, +-1.05164014555214358751e-04, +-1.05693117929663829482e-04, +-1.06161060575574886056e-04, +-1.06567663052451822372e-04, +-1.06912781257252219227e-04, +-1.07196306455972030416e-04, +-1.07418165294943403058e-04, +-1.07578319791868081681e-04, +-1.07676767306620711079e-04, +-1.07713540491867520218e-04, +-1.07688707223558459772e-04, +-1.07602370511359431062e-04, +-1.07454668389108225495e-04, +-1.07245773785382550523e-04, +-1.06975894374283873184e-04, +-1.06645272406552399651e-04, +-1.06254184521135326192e-04, +-1.05802941537346746376e-04, +-1.05291888227765690245e-04, +-1.04721403072029775822e-04, +-1.04091897991691806000e-04, +-1.03403818066321226388e-04, +-1.02657641231036926891e-04, +-1.01853877955673766901e-04, +-1.00993070905791316192e-04, +-1.00075794585747357554e-04, +-9.91026549640561086902e-05, +-9.80742890812979042133e-05, +-9.69913646407931124161e-05, +-9.58545795823286168359e-05, +-9.46646616391909589408e-05, +-9.34223678787874924024e-05, +-9.21284842271553308570e-05, +-9.07838249776128224534e-05, +-8.93892322839143330148e-05, +-8.79455756381782092872e-05, +-8.64537513339248380991e-05, +-8.49146819145573397919e-05, +-8.33293156075965769404e-05, +-8.16986257450709826454e-05, +-8.00236101703410545325e-05, +-7.83052906317712431187e-05, +-7.65447121635933332108e-05, +-7.47429424543394473968e-05, +-7.29010712032219468804e-05, +-7.10202094648487806125e-05, +-6.91014889826641889262e-05, +-6.71460615115136803116e-05, +-6.51550981297363063834e-05, +-6.31297885411947681941e-05, +-6.10713403676550390092e-05, +-5.89809784319366008933e-05, +-5.68599440322564117804e-05, +-5.47094942081945308492e-05, +-5.25309009987145816302e-05, +-5.03254506926742041614e-05, +-4.80944430722666716100e-05, +-4.58391906498364391982e-05, +-4.35610178985148694948e-05, +-4.12612604771267081670e-05, +-3.89412644498179452723e-05, +-3.66023855008608539076e-05, +-3.42459881450970870078e-05, +-3.18734449344449372976e-05, +-2.94861356610133087193e-05, +-2.70854465571730438690e-05, +-2.46727694931252419688e-05, +-2.22495011724306296223e-05, +-1.98170423258837072170e-05, +-1.73767969043094321503e-05, +-1.49301712706606661907e-05, +-1.24785733919144050828e-05, +-1.00234120312237155384e-05, +-7.56609594078786384176e-06, +-5.10803305590721484829e-06, +-2.65062969064796876903e-06, +-1.95289735662093879841e-07, + 2.25658614149781538763e-06, + 4.70360129302714707189e-06, + 7.14436388406460956736e-06, + 9.57748768197934699769e-06, + 1.20015928413035928855e-05, + 1.44153066838678001481e-05, + 1.68172644736985684973e-05, + 1.92061101862432256275e-05, + 2.15804972714890652230e-05, + 2.39390894105489946330e-05, + 2.62805612652901807722e-05, + 2.86035992205861757688e-05, + 3.09069021187789754650e-05, + 3.31891819859409621185e-05, + 3.54491647495335673412e-05, + 3.76855909470640991661e-05, + 3.98972164253476286417e-05, + 4.20828130299881090571e-05, + 4.42411692846974037292e-05, + 4.63710910600786401664e-05, + 4.84714022315057565344e-05, + 5.05409453257393869504e-05, + 5.25785821559190830470e-05, + 5.45831944446160030582e-05, + 5.65536844345369244078e-05, + 5.84889754866179482624e-05, + 6.03880126651817544857e-05, + 6.22497633097759614507e-05, + 6.40732175934516200036e-05, + 6.58573890671531589130e-05, + 6.76013151899331594073e-05, + 6.93040578447094631495e-05, + 7.09647038392890094557e-05, + 7.25823653923957063478e-05, + 7.41561806044386303671e-05, + 7.56853139127996218504e-05, + 7.71689565313425266486e-05, + 7.86063268739927838722e-05, + 7.99966709621114031078e-05, + 8.13392628154750729503e-05, + 8.26334048266602784602e-05, + 8.38784281186408519097e-05, + 8.50736928854174478216e-05, + 8.62185887155113381969e-05, + 8.73125348981630282396e-05, + 8.83549807120687932067e-05, + 8.93454056965571380595e-05, + 9.02833199050315720431e-05, + 9.11682641405671851135e-05, + 9.19998101735852404819e-05, + 9.27775609414710033911e-05, + 9.35011507300643465376e-05, + 9.41702453369411529019e-05, + 9.47845422164207620109e-05, + 9.53437706062401266714e-05, + 9.58476916358535753569e-05, + 9.62960984163175226676e-05, + 9.66888161117409645909e-05, + 9.70257019922829883106e-05, + 9.73066454687029886274e-05, + 9.75315681084497403076e-05, + 9.77004236333403651774e-05, + 9.78131978988259413559e-05, + 9.78699088548996316969e-05, + 9.78706064886931931908e-05, + 9.78153727488194655671e-05, + 9.77043214515344428731e-05, + 9.75375981687954049385e-05, + 9.73153800983090819503e-05, + 9.70378759156690566361e-05, + 9.67053256086932366224e-05, + 9.63180002940841964183e-05, + 9.58762020165379531865e-05, + 9.53802635304530459226e-05, + 9.48305480643773406665e-05, + 9.42274490683603826915e-05, + 9.35713899443812172551e-05, + 9.28628237600275093996e-05, + 9.21022329456168908045e-05, + 9.12901289749561102105e-05, + 9.04270520299548278501e-05, + 8.95135706492842500494e-05, + 8.85502813613394572714e-05, + 8.75378083017155033231e-05, + 8.64768028154355933648e-05, + 8.53679430442136669664e-05, + 8.42119334989644183860e-05, + 8.30095046178623384566e-05, + 8.17614123102081163550e-05, + 8.04684374863896741690e-05, + 7.91313855742244295563e-05, + 7.77510860219827716839e-05, + 7.63283917883946329882e-05, + 7.48641788199511630389e-05, + 7.33593455158201108654e-05, + 7.18148121806984416748e-05, + 7.02315204659344010599e-05, + 6.86104327992547092423e-05, + 6.69525318034425696596e-05, + 6.52588197043136263292e-05, + 6.35303177283451494866e-05, + 6.17680654903193261922e-05, + 5.99731203713451578997e-05, + 5.81465568876299857470e-05, + 5.62894660503753302872e-05, + 5.44029547171763266846e-05, + 5.24881449353098910931e-05, + 5.05461732772982176055e-05, + 4.85781901691450268576e-05, + 4.65853592116120024023e-05, + 4.45688564950032751967e-05, + 4.25298699077687427554e-05, + 4.04695984393985014349e-05, + 3.83892514779906950887e-05, + 3.62900481029001826128e-05, + 3.41732163729119983926e-05, + 3.20399926102781816627e-05, + 2.98916206811338720545e-05, + 2.77293512726352792174e-05, + 2.55544411672685861127e-05, + 2.33681525147488944956e-05, + 2.11717521018997930282e-05, + 1.89665106210108342917e-05, + 1.67537019369919437987e-05, + 1.45346023538229485151e-05, + 1.23104898806885715561e-05, + 1.00826434982246897416e-05, + 7.85234242529587054475e-06, + 5.62086538672328424332e-06, + 3.38948988238076994443e-06, + 1.15949145807567223944e-06, +-1.06785702137072707871e-06, +-3.29128609643022805093e-06, +-5.50953043415126442282e-06, +-7.72132954601048490098e-06, +-9.92542850192639466761e-06, +-1.21205786400318798465e-05, +-1.43055382718054505098e-05, +-1.64790733821644087950e-05, +-1.86399583241264707630e-05, +-2.07869765076501085866e-05, +-2.29189210822677048591e-05, +-2.50345956131302830444e-05, +-2.71328147500858357817e-05, +-2.92124048894140672726e-05, +-3.12722048278788822620e-05, +-3.33110664086613662642e-05, +-3.53278551589146714283e-05, +-3.73214509185134290983e-05, +-3.92907484596808479252e-05, +-4.12346580971520483842e-05, +-4.31521062885095992652e-05, +-4.50420362244331414815e-05, +-4.69034084084459727392e-05, +-4.87352012259119438489e-05, +-5.05364115019466182167e-05, +-5.23060550479419978189e-05, +-5.40431671964060976313e-05, +-5.57468033238534737064e-05, +-5.74160393614016982132e-05, +-5.90499722928839986262e-05, +-6.06477206401485110371e-05, +-6.22084249353098108415e-05, +-6.37312481796986922324e-05, +-6.52153762892660273948e-05, +-6.66600185262068023343e-05, +-6.80644079165767824100e-05, +-6.94278016536845402323e-05, +-7.07494814870478466295e-05, +-7.20287540967148501693e-05, +-7.32649514527553767347e-05, +-7.44574311597405420022e-05, +-7.56055767860350496235e-05, +-7.67087981777354925789e-05, +-7.77665317570998471846e-05, +-7.87782408053171710489e-05, +-7.97434157294830232507e-05, +-8.06615743136474125027e-05, +-8.15322619538178135472e-05, +-8.23550518768057822480e-05, +-8.31295453428154712148e-05, +-8.38553718316820378541e-05, +-8.45321892126865308053e-05, +-8.51596838978487685485e-05, +-8.57375709786715794677e-05, +-8.62655943462551288645e-05, +-8.67435267947428979536e-05, +-8.71711701080811815620e-05, +-8.75483551300409708427e-05, +-8.78749418175082112241e-05, +-8.81508192770273922871e-05, +-8.83759057846058285928e-05, +-8.85501487887902459777e-05, +-8.86735248970403253620e-05, +-8.87460398454319876341e-05, +-8.87677284517321478442e-05, +-8.87386545518955844984e-05, +-8.86589109200488812183e-05, +-8.85286191720270214433e-05, +-8.83479296525471903935e-05, +-8.81170213061050432417e-05, +-8.78361015316937552991e-05, +-8.75054060214538136477e-05, +-8.71251985833677709175e-05, +-8.66957709481281274576e-05, +-8.62174425603089747113e-05, +-8.56905603539940554595e-05, +-8.51154985129900034952e-05, +-8.44926582158212472655e-05, +-8.38224673656400427703e-05, +-8.31053803052506274724e-05, +-8.23418775174244912257e-05, +-8.15324653107033707304e-05, +-8.06776754908900028181e-05, +-7.97780650184373106007e-05, +-7.88342156519530526523e-05, +-7.78467335780445683635e-05, +-7.68162490277368720107e-05, +-7.57434158797055202611e-05, +-7.46289112505573565791e-05, +-7.34734350724463647960e-05, +-7.22777096582538457334e-05, +-7.10424792545960120905e-05, +-6.97685095829731762810e-05, +-6.84565873693016984378e-05, +-6.71075198621341007877e-05, +-6.57221343398554209113e-05, +-6.43012776071557890780e-05, +-6.28458154810835923102e-05, +-6.13566322669881414808e-05, +-5.98346302246723383829e-05, +-5.82807290250536745514e-05, +-5.66958651977116231350e-05, +-5.50809915695821473340e-05, +-5.34370766951852471703e-05, +-5.17651042787056485015e-05, +-5.00660725882709159050e-05, +-4.83409938627764752253e-05, +-4.65908937116066385552e-05, +-4.48168105076074261466e-05, +-4.30197947736637000340e-05, +-4.12009085632678118496e-05, +-3.93612248353795128467e-05, +-3.75018268240328908462e-05, +-3.56238074029696449125e-05, +-3.37282684457607440684e-05, +-3.18163201816986404395e-05, +-2.98890805479001212680e-05, +-2.79476745379709999822e-05, +-2.59932335476144176260e-05, +-2.40268947175631300377e-05, +-2.20498002742151532848e-05, +-2.00630968683545589837e-05, +-1.80679349123383810435e-05, +-1.60654679161321810180e-05, +-1.40568518225757011658e-05, +-1.20432443422608051199e-05, +-1.00258042884029404491e-05, +-8.00569091208727099719e-06, +-5.98406323826935972361e-06, +-3.96207940290984570201e-06, +-1.94089599162064887166e-06, + 7.83326198005747898907e-08, + 2.09445492257301924948e-06, + 4.10632292949940006763e-06, + 6.11279282652582891513e-06, + 8.11272562092629197044e-06, + 1.01049877857409114437e-05, + 1.20884519001330790116e-05, + 1.40619972852336154977e-05, + 1.60245106352098204275e-05, + 1.79748866431337342073e-05, + 1.99120286213276946629e-05, + 2.18348491158356895975e-05, + 2.37422705146771266798e-05, + 2.56332256495490372664e-05, + 2.75066583906145059298e-05, + 2.93615242341154332678e-05, + 3.11967908823933051383e-05, + 3.30114388160605143471e-05, + 3.48044618580061525877e-05, + 3.65748677288642252687e-05, + 3.83216785937263849210e-05, + 4.00439315997342949434e-05, + 4.17406794042833988461e-05, + 4.34109906935455636926e-05, + 4.50539506910283595867e-05, + 4.66686616558951677231e-05, + 4.82542433707754188257e-05, + 4.98098336188025105076e-05, + 5.13345886496223527710e-05, + 5.28276836341212981227e-05, + 5.42883131076322484254e-05, + 5.57156914013806444015e-05, + 5.71090530619421132309e-05, + 5.84676532584898041777e-05, + 5.97907681776162523235e-05, + 6.10776954055230943694e-05, + 6.23277542973780997616e-05, + 6.35402863336491786732e-05, + 6.47146554632286333470e-05, + 6.58502484331734486145e-05, + 6.69464751048926757886e-05, + 6.80027687566194964435e-05, + 6.90185863720170044832e-05, + 6.99934089147837939756e-05, + 7.09267415890902172158e-05, + 7.18181140857647161381e-05, + 7.26670808140748066949e-05, + 7.34732211190075503587e-05, + 7.42361394839436268501e-05, + 7.49554657186243128170e-05, + 7.56308551323502581193e-05, + 7.62619886923002242643e-05, + 7.68485731669290054405e-05, + 7.73903412543740319013e-05, + 7.78870516958209856877e-05, + 7.83384893737935715909e-05, + 7.87444653953147782324e-05, + 7.91048171599420551657e-05, + 7.94194084126392720741e-05, + 7.96881292814878859675e-05, + 7.99108963002358391528e-05, + 8.00876524156968731425e-05, + 8.02183669800153831232e-05, + 8.03030357278285665534e-05, + 8.03416807383593541874e-05, + 8.03343503824849146247e-05, + 8.02811192548356472283e-05, + 8.01820880909844978159e-05, + 8.00373836697980867074e-05, + 7.98471587010282266798e-05, + 7.96115916982296047740e-05, + 7.93308868371003252356e-05, + 7.90052737993477842459e-05, + 7.86350076021916034787e-05, + 7.82203684136235352425e-05, + 7.77616613535522615110e-05, + 7.72592162809664708160e-05, + 7.67133875672632579209e-05, + 7.61245538558890809302e-05, + 7.54931178084552014299e-05, + 7.48195058374859282803e-05, + 7.41041678259918263445e-05, + 7.33475768340236086891e-05, + 7.25502287924132663235e-05, + 7.17126421838883761507e-05, + 7.08353577117746115253e-05, + 6.99189379564657824580e-05, + 6.89639670199154882456e-05, + 6.79710501583437364317e-05, + 6.69408134033987737470e-05, + 6.58739031720058094803e-05, + 6.47709858651478100500e-05, + 6.36327474558071720916e-05, + 6.24598930663620521917e-05, + 6.12531465356429315541e-05, + 6.00132499759513726788e-05, + 5.87409633202952744489e-05, + 5.74370638601181475024e-05, + 5.61023457738005077431e-05, + 5.47376196462178894200e-05, + 5.33437119796454611961e-05, + 5.19214646963013157221e-05, + 5.04717346328268796885e-05, + 4.89953930270064014403e-05, + 4.74933249970308410371e-05, + 4.59664290136169696407e-05, + 4.44156163652937726011e-05, + 4.28418106171734954413e-05, + 4.12459470635278838894e-05, + 3.96289721744912600845e-05, + 3.79918430372181689441e-05, + 3.63355267918223325723e-05, + 3.46610000624296407993e-05, + 3.29692483836776077948e-05, + 3.12612656229971128227e-05, + 2.95380533990134290555e-05, + 2.78006204964105713487e-05, + 2.60499822775738051233e-05, + 2.42871600914147949164e-05, + 2.25131806796356132906e-05, + 2.07290755808621738894e-05, + 1.89358805329046950760e-05, + 1.71346348735776756247e-05, + 1.53263809403626031776e-05, + 1.35121634692837809516e-05, + 1.16930289933384643446e-05, + 9.87002524082706459254e-06, + 8.04420053392769432833e-06, + 6.21660318786371497718e-06, + 4.38828091098144307670e-06, + 2.56028020614524101076e-06, + 7.33645773704159215729e-07, +-1.09058008356538882663e-06, +-2.91135805322907028961e-06, +-4.72765240333595687151e-06, +-6.53843156959771685090e-06, +-8.34266873927393720254e-06, +-1.01393424314343474083e-05, +-1.19274370732709349764e-05, +-1.37059435721405858846e-05, +-1.54738598829871196378e-05, +-1.72301915709141233841e-05, +-1.89739523684456172069e-05, +-2.07041647273114594839e-05, +-2.24198603643615891102e-05, +-2.41200808013344202745e-05, +-2.58038778981763044563e-05, +-2.74703143796157200874e-05, +-2.91184643547017321143e-05, +-3.07474138290197399233e-05, +-3.23562612093023567895e-05, +-3.39441178001584614038e-05, +-3.55101082926439871944e-05, +-3.70533712444301888567e-05, +-3.85730595512544287501e-05, +-4.00683409094500665032e-05, +-4.15383982693033816007e-05, +-4.29824302789406134098e-05, +-4.43996517185575042359e-05, +-4.57892939247349858053e-05, +-4.71506052046175686584e-05, +-4.84828512397324982693e-05, +-4.97853154792346060619e-05, +-5.10572995223683090350e-05, +-5.22981234899434565362e-05, +-5.35071263846277400461e-05, +-5.46836664398836234187e-05, +-5.58271214573224499331e-05, +-5.69368891323614851295e-05, +-5.80123873679696164230e-05, +-5.90530545763586015842e-05, +-6.00583499684634902521e-05, +-6.10277538310640554767e-05, +-6.19607677914099007560e-05, +-6.28569150692159534649e-05, +-6.37157407158944321529e-05, +-6.45368118409359687801e-05, +-6.53197178252850279385e-05, +-6.60640705216541051321e-05, +-6.67695044416362863812e-05, +-6.74356769295752540719e-05, +-6.80622683230799142623e-05, +-6.86489821001279852154e-05, +-6.91955450126904592642e-05, +-6.97017072068230802637e-05, +-7.01672423291767658176e-05, +-7.05919476198861947256e-05, +-7.09756439918057140982e-05, +-7.13181760960681986961e-05, +-7.16194123739501793333e-05, +-7.18792450950348377767e-05, +-7.20975903816736135316e-05, +-7.22743882197516537879e-05, +-7.24096024557741556067e-05, +-7.25032207802958942548e-05, +-7.25552546977243766621e-05, +-7.25657394825357868065e-05, +-7.25347341219498558274e-05, +-7.24623212451169996162e-05, +-7.23486070388806753713e-05, +-7.21937211501822589683e-05, +-7.19978165751875085875e-05, +-7.17610695352167158104e-05, +-7.14836793395702676862e-05, +-7.11658682353526731877e-05, +-7.08078812443949090743e-05, +-7.04099859873934258306e-05, +-6.99724724953850081566e-05, +-6.94956530086853716552e-05, +-6.89798617634244460098e-05, +-6.84254547658288183589e-05, +-6.78328095543798148277e-05, +-6.72023249500277669805e-05, +-6.65344207946062419579e-05, +-6.58295376776219041525e-05, +-6.50881366515859591205e-05, +-6.43106989360903185575e-05, +-6.34977256107851671055e-05, +-6.26497372974739176162e-05, +-6.17672738315155477485e-05, +-6.08508939227416309091e-05, +-5.99011748060970076221e-05, +-5.89187118822223946605e-05, +-5.79041183481987132707e-05, +-5.68580248186811984187e-05, +-5.57810789376551931251e-05, +-5.46739449810503702100e-05, +-5.35373034504554770174e-05, +-5.23718506581807131213e-05, +-5.11782983039181917171e-05, +-4.99573730432570882465e-05, +-4.87098160483125057073e-05, +-4.74363825607329001348e-05, +-4.61378414373535389293e-05, +-4.48149746887680454615e-05, +-4.34685770110934173059e-05, +-4.20994553112074291123e-05, +-4.07084282257405295205e-05, +-3.92963256341110296946e-05, +-3.78639881658720183844e-05, +-3.64122667027106395048e-05, +-3.49420218753273198247e-05, +-3.34541235555410240970e-05, +-3.19494503438986083817e-05, +-3.04288890530928917170e-05, +-2.88933341874874255505e-05, +-2.73436874190750308462e-05, +-2.57808570601205806739e-05, +-2.42057575328682884756e-05, +-2.26193088365677101494e-05, +-2.10224360121490399698e-05, +-1.94160686048590696543e-05, +-1.78011401251455341182e-05, +-1.61785875081583371295e-05, +-1.45493505721038791060e-05, +-1.29143714758213699049e-05, +-1.12745941758700444585e-05, +-9.63096388344320252515e-06, +-7.98442652142029617504e-06, +-6.33592818186786765829e-06, +-4.68641458429933138496e-06, +-3.03683053500296397801e-06, +-1.38811938774586377356e-06, + 2.58777493839178202322e-07, + 1.90292127187864929960e-06, + 3.54337616759140759028e-06, + 5.17920999202801067562e-06, + 6.80949467391633912354e-06, + 8.43330678431570807498e-06, + 1.00497280577839181130e-05, + 1.16578459097642718917e-05, + 1.32567539499020862689e-05, + 1.48455524910031115056e-05, + 1.64233490533491062295e-05, + 1.79892588640891236808e-05, + 1.95424053514245014756e-05, + 2.10819206333345681716e-05, + 2.26069460005168742459e-05, + 2.41166323933478058403e-05, + 2.56101408725446344061e-05, + 2.70866430832949805965e-05, + 2.85453217125733007859e-05, + 2.99853709394462142215e-05, + 3.14059968780488809876e-05, + 3.28064180130436779592e-05, + 3.41858656273021432946e-05, + 3.55435842215810670545e-05, + 3.68788319259649065773e-05, + 3.81908809028492260114e-05, + 3.94790177412656769699e-05, + 4.07425438422898093392e-05, + 4.19807757953880351259e-05, + 4.31930457454549954818e-05, + 4.43787017503647075972e-05, + 4.55371081288425238044e-05, + 4.66676457984745168698e-05, + 4.77697126036755268658e-05, + 4.88427236334443488387e-05, + 4.98861115287400902485e-05, + 5.08993267793200968442e-05, + 5.18818380098863440766e-05, + 5.28331322553930322872e-05, + 5.37527152253746494555e-05, + 5.46401115571613411491e-05, + 5.54948650578534959663e-05, + 5.63165389349345359561e-05, + 5.71047160154089449252e-05, + 5.78589989533570669814e-05, + 5.85790104258065492428e-05, + 5.92643933168274041653e-05, + 5.99148108897627355894e-05, + 6.05299469475165509511e-05, + 6.11095059808236870788e-05, + 6.16532133044444885040e-05, + 6.21608151812043867963e-05, + 6.26320789338565816822e-05, + 6.30667930446937390586e-05, + 6.34647672428986905826e-05, + 6.38258325795768347542e-05, + 6.41498414904665125455e-05, + 6.44366678463023396118e-05, + 6.46862069908247323737e-05, + 6.48983757664325786518e-05, + 6.50731125274843654437e-05, + 6.52103771412599882238e-05, + 6.53101509766035163464e-05, + 6.53724368802683817540e-05, + 6.53972591410049980528e-05, + 6.53846634414262362599e-05, + 6.53347167976985163280e-05, + 6.52475074871135241571e-05, + 6.51231449636010796761e-05, + 6.49617597612497395644e-05, + 6.47635033859116657304e-05, + 6.45285481949697814485e-05, + 6.42570872653582068207e-05, + 6.39493342499302042841e-05, + 6.36055232222692201391e-05, + 6.32259085100558739911e-05, + 6.28107645171077595475e-05, + 6.23603855342008971162e-05, + 6.18750855388094879363e-05, + 6.13551979838913776489e-05, + 6.08010755758598702586e-05, + 6.02130900418846006969e-05, + 5.95916318866736676439e-05, + 5.89371101388912814706e-05, + 5.82499520873748857785e-05, + 5.75306030073172492193e-05, + 5.67795258765894393974e-05, + 5.59972010823701890950e-05, + 5.51841261183018495025e-05, + 5.43408152723015371618e-05, + 5.34677993052802834643e-05, + 5.25656251209348160261e-05, + 5.16348554268246720794e-05, + 5.06760683869446402865e-05, + 4.96898572660009552938e-05, + 4.86768300656121986501e-05, + 4.76376091526542401900e-05, + 4.65728308799746458426e-05, + 4.54831451997094723732e-05, + 4.43692152694205702067e-05, + 4.32317170513272638010e-05, + 4.20713389048248215750e-05, + 4.08887811725691820543e-05, + 3.96847557603624830438e-05, + 3.84599857110910642592e-05, + 3.72152047729705208619e-05, + 3.59511569623536525052e-05, + 3.46685961213579385467e-05, + 3.33682854705920874040e-05, + 3.20509971572010551400e-05, + 3.07175117985585750834e-05, + 2.93686180218123159854e-05, + 2.80051119996170835922e-05, + 2.66277969822622470077e-05, + 2.52374828265144898710e-05, + 2.38349855214322459531e-05, + 2.24211267114313739257e-05, + 2.09967332168798777813e-05, + 1.95626365525002586521e-05, + 1.81196724438590493929e-05, + 1.66686803422232323734e-05, + 1.52105029380648706125e-05, + 1.37459856734939339152e-05, + 1.22759762539012447631e-05, + 1.08013241590919135580e-05, + 9.32288015419072379738e-06, + 7.84149580059962841079e-06, + 6.35802296728773956217e-06, + 4.87331334269314813773e-06, + 3.38821794751525819401e-06, + 1.90358664867536025810e-06, + 4.20267674722007678397e-07, +-1.06089286704349063181e-06, +-2.53905147144755971960e-06, +-4.01336771405853671665e-06, +-5.48300472726051319248e-06, +-6.94712967353908428204e-06, +-8.40491421565995491089e-06, +-9.85553498354600196257e-06, +-1.12981740375379932287e-05, +-1.27320193278005813889e-05, +-1.41562651496129757108e-05, +-1.55701125942935366840e-05, +-1.69727699954863943171e-05, +-1.83634533706132413357e-05, +-1.97413868571768872317e-05, +-2.11058031437259111299e-05, +-2.24559438952188090413e-05, +-2.37910601725753876787e-05, +-2.51104128461361075818e-05, +-2.64132730028669993332e-05, +-2.76989223470385161768e-05, +-2.89666535941785825052e-05, +-3.02157708580817170672e-05, +-3.14455900306639634365e-05, +-3.26554391544575276863e-05, +-3.38446587875432448227e-05, +-3.50126023607246299988e-05, +-3.61586365267507298072e-05, +-3.72821415014014433467e-05, +-3.83825113962520523994e-05, +-3.94591545429407643156e-05, +-4.05114938087662831479e-05, +-4.15389669034495396562e-05, +-4.25410266768976613630e-05, +-4.35171414078138610380e-05, +-4.44667950830035220650e-05, +-4.53894876672311637202e-05, +-4.62847353634881464551e-05, +-4.71520708635396170122e-05, +-4.79910435886203451676e-05, +-4.88012199201597561809e-05, +-4.95821834204167205301e-05, +-5.03335350429265633945e-05, +-5.10548933326265304408e-05, +-5.17458946156012646414e-05, +-5.24061931783268363742e-05, +-5.30354614363393909939e-05, +-5.36333900922485962647e-05, +-5.41996882830139510762e-05, +-5.47340837164388594079e-05, +-5.52363227967925824054e-05, +-5.57061707395272917836e-05, +-5.61434116750343203787e-05, +-5.65478487413978341881e-05, +-5.69193041661166998697e-05, +-5.72576193367504884379e-05, +-5.75626548604881785863e-05, +-5.78342906126072504132e-05, +-5.80724257738199440486e-05, +-5.82769788565022921634e-05, +-5.84478877198096668589e-05, +-5.85851095736871960683e-05, +-5.86886209717912786239e-05, +-5.87584177933450407718e-05, +-5.87945152139549069526e-05, +-5.87969476654236840492e-05, +-5.87657687846015756232e-05, +-5.87010513513210692091e-05, +-5.86028872154704082165e-05, +-5.84713872132640056231e-05, +-5.83066810727762474998e-05, +-5.81089173088098371331e-05, +-5.78782631071765932274e-05, +-5.76149041984740298956e-05, +-5.73190447214473209757e-05, +-5.69909070760322414208e-05, +-5.66307317661793541358e-05, +-5.62387772325672526141e-05, +-5.58153196753171827195e-05, +-5.53606528668218819548e-05, +-5.48750879548260181830e-05, +-5.43589532558681387997e-05, +-5.38125940392313040217e-05, +-5.32363723015430049873e-05, +-5.26306665321520585781e-05, +-5.19958714694554905247e-05, +-5.13323978483126871185e-05, +-5.06406721387124545189e-05, +-4.99211362758563274877e-05, +-4.91742473818266735545e-05, +-4.84004774790149961978e-05, +-4.76003131954764758258e-05, +-4.67742554624208601633e-05, +-4.59228192039893781543e-05, +-4.50465330195347888644e-05, +-4.41459388585886764659e-05, +-4.32215916887159588432e-05, +-4.22740591564579529368e-05, +-4.13039212415705373426e-05, +-4.03117699047655450996e-05, +-3.92982087291690829157e-05, +-3.82638525557110084044e-05, +-3.72093271126660717248e-05, +-3.61352686395672686765e-05, +-3.50423235057168379857e-05, +-3.39311478235224090556e-05, +-3.28024070568877919004e-05, +-3.16567756248915059525e-05, +-3.04949365009877199171e-05, +-2.93175808079664161425e-05, +-2.81254074089120697057e-05, +-2.69191224944017248270e-05, +-2.56994391661852553642e-05, +-2.44670770175918836234e-05, +-2.32227617109122020126e-05, +-2.19672245519847623529e-05, +-2.07012020622797709220e-05, +-1.94254355486677272565e-05, +-1.81406706711849960521e-05, +-1.68476570089850853130e-05, +-1.55471476247899104671e-05, +-1.42398986280482303988e-05, +-1.29266687370718316063e-05, +-1.16082188403988693324e-05, +-1.02853115576371897586e-05, +-8.95871080003975092416e-06, +-7.62918133106494951846e-06, +-6.29748832717637000583e-06, +-4.96439693911456911849e-06, +-3.63067185393867396159e-06, +-2.29707685802459498842e-06, +-9.64374401315848450426e-07, + 3.66674836944231519952e-07, + 1.69531238074935703441e-06, + 3.02078238789119312040e-06, + 4.34233207830084875904e-06, + 5.65921215992918806928e-06, + 6.97067725192901449440e-06, + 8.27598630488246552004e-06, + 9.57440301788133736832e-06, + 1.08651962521827093731e-05, + 1.21476404412087555200e-05, + 1.34210159967052598768e-05, + 1.46846097107889237831e-05, + 1.59377151536783862637e-05, + 1.71796330668853545218e-05, + 1.84096717516477081152e-05, + 1.96271474523901250152e-05, + 2.08313847350004374291e-05, + 2.20217168597138741371e-05, + 2.31974861483999769760e-05, + 2.43580443460485478093e-05, + 2.55027529762765186715e-05, + 2.66309836906033699266e-05, + 2.77421186114023531077e-05, + 2.88355506682450058473e-05, + 2.99106839275143976181e-05, + 3.09669339150908589178e-05, + 3.20037279319387916966e-05, + 3.30205053624261607144e-05, + 3.40167179752114232517e-05, + 3.49918302165381128787e-05, + 3.59453194957816331854e-05, + 3.68766764630972321086e-05, + 3.77854052790209193153e-05, + 3.86710238758958244651e-05, + 3.95330642109541764121e-05, + 4.03710725109682755916e-05, + 4.11846095083103026020e-05, + 4.19732506683146705116e-05, + 4.27365864078233130617e-05, + 4.34742223048040452049e-05, + 4.41857792989385563150e-05, + 4.48708938830692915926e-05, + 4.55292182854370863364e-05, + 4.61604206425851002231e-05, + 4.67641851628709925696e-05, + 4.73402122805066265026e-05, + 4.78882188000329483382e-05, + 4.84079380311931386409e-05, + 4.88991199141192096943e-05, + 4.93615311347864993397e-05, + 4.97949552306842973051e-05, + 5.01991926866579958816e-05, + 5.05740610208843503087e-05, + 5.09193948609473228035e-05, + 5.12350460099867614349e-05, + 5.15208835028994156444e-05, + 5.17767936525754493993e-05, + 5.20026800861617919140e-05, + 5.21984637713472843972e-05, + 5.23640830326715540628e-05, + 5.24994935578649676486e-05, + 5.26046683942319904669e-05, + 5.26795979350977647813e-05, + 5.27242898963412381865e-05, + 5.27387692830453080699e-05, + 5.27230783462991780706e-05, + 5.26772765301947225270e-05, + 5.26014404090633305310e-05, + 5.24956636150047901762e-05, + 5.23600567557668073533e-05, + 5.21947473230388830738e-05, + 5.19998795912271193358e-05, + 5.17756145067857189357e-05, + 5.15221295681833840827e-05, + 5.12396186965899134232e-05, + 5.09282920973702621955e-05, + 5.05883761124873977634e-05, + 5.02201130639010932745e-05, + 4.98237610880825857601e-05, + 4.93995939617437136368e-05, + 4.89479009189001211121e-05, + 4.84689864593871208814e-05, + 4.79631701489468674927e-05, + 4.74307864110306472431e-05, + 4.68721843104290958456e-05, + 4.62877273288830334104e-05, + 4.56777931328110654310e-05, + 4.50427733333015571236e-05, + 4.43830732385187975314e-05, + 4.36991115986785094998e-05, + 4.29913203437512904219e-05, + 4.22601443140560245420e-05, + 4.15060409839102542823e-05, + 4.07294801785067884332e-05, + 3.99309437841909614544e-05, + 3.91109254523149503578e-05, + 3.82699302968499331071e-05, + 3.74084745859401725113e-05, + 3.65270854275851831246e-05, + 3.56263004496409294844e-05, + 3.47066674743320204575e-05, + 3.37687441874715604177e-05, + 3.28130978025864834921e-05, + 3.18403047201496259048e-05, + 3.08509501821220885999e-05, + 2.98456279220141111716e-05, + 2.88249398106583463292e-05, + 2.77894954979411405727e-05, + 2.67399120506568739174e-05, + 2.56768135867345998077e-05, + 2.46008309060387078085e-05, + 2.35126011179608967452e-05, + 2.24127672660373206972e-05, + 2.13019779497730199318e-05, + 2.01808869439458528371e-05, + 1.90501528155745074983e-05, + 1.79104385387887921337e-05, + 1.67624111078244624493e-05, + 1.56067411483699600464e-05, + 1.44441025274743162915e-05, + 1.32751719622829946729e-05, + 1.21006286277736464400e-05, + 1.09211537637588811984e-05, + 9.73743028136644528262e-06, + 8.55014236922561691437e-06, + 7.35997509958635033394e-06, + 6.16761403459692181825e-06, + 4.97374483296533837542e-06, + 3.77905285722950647743e-06, + 2.58422278186008839003e-06, + 1.38993820241930683239e-06, + 1.96881245997903772338e-07, +-9.94267816848598569217e-07, +-2.18283095844447963890e-06, +-3.36813277840069707876e-06, +-4.54950088586700000424e-06, +-5.72626627941386950107e-06, +-6.89776372433048807836e-06, +-8.06333212712694707145e-06, +-9.22231490703067589279e-06, +-1.03740603642693244191e-05, +-1.15179220449344173161e-05, +-1.26532591022196861730e-05, +-1.37794366538495711072e-05, +-1.48958261354584999990e-05, +-1.60018056497799296184e-05, +-1.70967603114136951952e-05, +-1.81800825869820380861e-05, +-1.92511726305242952264e-05, +-2.03094386138927829864e-05, +-2.13542970520092069756e-05, +-2.23851731227873900821e-05, +-2.34015009815511875976e-05, +-2.44027240697762211102e-05, +-2.53882954179860686225e-05, +-2.63576779426533689202e-05, +-2.73103447369098503218e-05, +-2.82457793549575378290e-05, +-2.91634760899918437553e-05, +-3.00629402455041167019e-05, +-3.09436883998153130820e-05, +-3.18052486637019455554e-05, +-3.26471609309779970515e-05, +-3.34689771219005548241e-05, +-3.42702614192727262341e-05, +-3.50505904971203557973e-05, +-3.58095537418260222574e-05, +-3.65467534655933827146e-05, +-3.72618051121717498101e-05, +-3.79543374546707974228e-05, +-3.86239927854306394216e-05, +-3.92704270978131317837e-05, +-3.98933102598363287456e-05, +-4.04923261795653974715e-05, +-4.10671729621785269976e-05, +-4.16175630586323642046e-05, +-4.21432234058559141441e-05, +-4.26438955584067616068e-05, +-4.31193358115292238756e-05, +-4.35693153155569312869e-05, +-4.39936201816156069303e-05, +-4.43920515785651946397e-05, +-4.47644258211561343495e-05, +-4.51105744493632472049e-05, +-4.54303442988531914885e-05, +-4.57235975625737596506e-05, +-4.59902118434391446694e-05, +-4.62300801980975147932e-05, +-4.64431111717703053654e-05, +-4.66292288241590738816e-05, +-4.67883727464197082162e-05, +-4.69204980692097139592e-05, +-4.70255754618213880035e-05, +-4.71035911224101212042e-05, +-4.71545467593474220552e-05, +-4.71784595637180143891e-05, +-4.71753621729942670049e-05, +-4.71453026259235373810e-05, +-4.70883443086696765927e-05, +-4.70045658922535814004e-05, +-4.68940612613444625227e-05, +-4.67569394344568726790e-05, +-4.65933244756150703129e-05, +-4.64033553975471216042e-05, +-4.61871860564808808737e-05, +-4.59449850386188616159e-05, +-4.56769355383655138421e-05, +-4.53832352283949652812e-05, +-4.50640961216473178623e-05, +-4.47197444253447825278e-05, +-4.43504203871267281252e-05, +-4.39563781334040550529e-05, +-4.35378855000395927045e-05, +-4.30952238554646824297e-05, +-4.26286879163457669119e-05, +-4.21385855559199974771e-05, +-4.16252376051221437895e-05, +-4.10889776466288376587e-05, +-4.05301518019508379771e-05, +-3.99491185117068837215e-05, +-3.93462483092169100062e-05, +-3.87219235875561562329e-05, +-3.80765383602142771309e-05, +-3.74104980155082837679e-05, +-3.67242190649002693526e-05, +-3.60181288853753334362e-05, +-3.52926654560366292231e-05, +-3.45482770890794257056e-05, +-3.37854221553090375610e-05, +-3.30045688043594255523e-05, +-3.22061946798075831645e-05, +-3.13907866293216945321e-05, +-3.05588404100427330412e-05, +-2.97108603893675688823e-05, +-2.88473592413132615716e-05, +-2.79688576386454084658e-05, +-2.70758839409515568225e-05, +-2.61689738788582883049e-05, +-2.52486702345479146949e-05, +-2.43155225188067227653e-05, +-2.33700866447662229544e-05, +-2.24129245985293835562e-05, +-2.14446041069073238181e-05, +-2.04656983024178883341e-05, +-1.94767853857754148804e-05, +-1.84784482860567825561e-05, +-1.74712743187444023349e-05, +-1.64558548418461311194e-05, +-1.54327849102923173909e-05, +-1.44026629288111792759e-05, +-1.33660903034842037365e-05, +-1.23236710921832843933e-05, +-1.12760116540923691986e-05, +-1.02237202985157386555e-05, +-9.16740693317562989567e-06, +-8.10768271220163393815e-06, +-7.04515968401436206049e-06, +-5.98045043930514029506e-06, +-4.91416775931360371891e-06, +-3.84692426460422025455e-06, +-2.77933206454218416435e-06, +-1.71200240766848139346e-06, +-6.45545333172962557628e-07, + 4.19430676336646794336e-07, + 1.48231904057302648397e-06, + 2.54251542561663930372e-06, + 3.59941808609308168670e-06, + 4.65242820524958869112e-06, + 5.70095023278988534811e-06, + 6.74439222023971488674e-06, + 7.78216615367016922942e-06, + 8.81368828359270617260e-06, + 9.83837945182666922020e-06, + 1.08556654151943217460e-05, + 1.18649771658138885200e-05, + 1.28657512478499302136e-05, + 1.38574300705307268156e-05, + 1.48394622172600090695e-05, + 1.58113027506664198453e-05, + 1.67724135133877546580e-05, + 1.77222634244721200859e-05, + 1.86603287711980042802e-05, + 1.95860934961685117974e-05, + 2.04990494795206747223e-05, + 2.13986968160965711628e-05, + 2.22845440874262652991e-05, + 2.31561086283755511721e-05, + 2.40129167883148332595e-05, + 2.48545041866689361690e-05, + 2.56804159627113593367e-05, + 2.64902070194693860814e-05, + 2.72834422616106000525e-05, + 2.80596968271851059942e-05, + 2.88185563131008925446e-05, + 2.95596169942142674564e-05, + 3.02824860359208226652e-05, + 3.09867817001359949951e-05, + 3.16721335445593264431e-05, + 3.23381826151192079948e-05, + 3.29845816314999765108e-05, + 3.36109951656569510029e-05, + 3.42170998132293449818e-05, + 3.48025843577636647915e-05, + 3.53671499276745119299e-05, + 3.59105101458437678133e-05, + 3.64323912718148200060e-05, + 3.69325323364901809465e-05, + 3.74106852692794952407e-05, + 3.78666150176288244058e-05, + 3.83000996588942581029e-05, + 3.87109305044850893402e-05, + 3.90989121962477274223e-05, + 3.94638627950426708552e-05, + 3.98056138614771284553e-05, + 4.01240105287611420687e-05, + 4.04189115676629857573e-05, + 4.06901894435291198787e-05, + 4.09377303653654542282e-05, + 4.11614343269538722871e-05, + 4.13612151399990495742e-05, + 4.15370004592994877942e-05, + 4.16887317999427647820e-05, + 4.18163645465287068582e-05, + 4.19198679544291165572e-05, + 4.19992251430971813499e-05, + 4.20544330814450761122e-05, + 4.20855025653108131916e-05, + 4.20924581870419940027e-05, + 4.20753382972270773108e-05, + 4.20341949586107831312e-05, + 4.19690938922323789214e-05, + 4.18801144158325268558e-05, + 4.17673493745770476031e-05, + 4.16309050641507942731e-05, + 4.14709011462787672121e-05, + 4.12874705567371297560e-05, + 4.10807594059191025335e-05, + 4.08509268720259451839e-05, + 4.05981450869582284656e-05, + 4.03225990149817188125e-05, + 4.00244863242588127953e-05, + 3.97040172513205211744e-05, + 3.93614144585763300172e-05, + 3.89969128849576671548e-05, + 3.86107595897814662080e-05, + 3.82032135899500682069e-05, + 3.77745456905820574433e-05, + 3.73250383091862464823e-05, + 3.68549852934909236125e-05, + 3.63646917330434846769e-05, + 3.58544737646997589589e-05, + 3.53246583721261741586e-05, + 3.47755831794332366546e-05, + 3.42075962390870128276e-05, + 3.36210558142060423280e-05, + 3.30163301553966777682e-05, + 3.23937972722568060207e-05, + 3.17538446996900900290e-05, + 3.10968692591733985816e-05, + 3.04232768151230764501e-05, + 2.97334820265093258108e-05, + 2.90279080938678783936e-05, + 2.83069865018621188567e-05, + 2.75711567575615524813e-05, + 2.68208661245598943643e-05, + 2.60565693531506030998e-05, + 2.52787284066631597003e-05, + 2.44878121841591343355e-05, + 2.36842962396411912224e-05, + 2.28686624979444416434e-05, + 2.20413989674784742564e-05, + 2.12029994499905229957e-05, + 2.03539632475213441687e-05, + 1.94947948667270345394e-05, + 1.86260037207404863615e-05, + 1.77481038287503190129e-05, + 1.68616135134610017573e-05, + 1.59670550966399525954e-05, + 1.50649545929016600080e-05, + 1.41558414019059438765e-05, + 1.32402479991802029098e-05, + 1.23187096257152244321e-05, + 1.13917639765278494500e-05, + 1.04599508883682767454e-05, + 9.52381202675309655368e-06, + 8.58389057250431938178e-06, + 7.64073090797513138387e-06, + 6.69487830314289765184e-06, + 5.74687860175188295145e-06, + 4.79727790767192774363e-06, + 3.84662227168647334824e-06, + 2.89545737884364760088e-06, + 1.94432823658253304009e-06, + 9.93778863798429985474e-07, + 4.43519810261418219453e-08, +-9.03411298083134494987e-07, +-1.84897177381668332505e-06, +-2.79179246581568572222e-06, +-3.73133891666547724968e-06, +-4.66707949352351104895e-06, +-5.59848568756837193684e-06, +-6.52503241114909488603e-06, +-7.44619829242155147390e-06, +-8.36146596735429801020e-06, +-9.27032236890755496482e-06, +-1.01722590132379665735e-05, +-1.10667722827682534897e-05, +-1.19533637059645449316e-05, +-1.28315402336673929602e-05, +-1.37008145118236726118e-05, +-1.45607051504696124636e-05, +-1.54107369888173211751e-05, +-1.62504413562997488372e-05, +-1.70793563294315240981e-05, +-1.78970269843458541098e-05, +-1.87030056448704560027e-05, +-1.94968521260079873374e-05, +-2.02781339726898497515e-05, +-2.10464266936743830125e-05, +-2.18013139904647730040e-05, +-2.25423879811231864039e-05, +-2.32692494188629845134e-05, +-2.39815079053020545374e-05, +-2.46787820982652636209e-05, +-2.53606999140241696946e-05, +-2.60268987238786572637e-05, +-2.66770255449520642306e-05, +-2.73107372251350898203e-05, +-2.79277006220566396152e-05, +-2.85275927760007770367e-05, +-2.91101010766786506953e-05, +-2.96749234237720292370e-05, +-3.02217683811674436194e-05, +-3.07503553247967688486e-05, +-3.12604145840304585829e-05, +-3.17516875765274536082e-05, +-3.22239269364954619744e-05, +-3.26768966362916865294e-05, +-3.31103721013135404044e-05, +-3.35241403181086740208e-05, +-3.39179999356772221173e-05, +-3.42917613599035768068e-05, +-3.46452468410814200988e-05, +-3.49782905544949971623e-05, +-3.52907386740210617191e-05, +-3.55824494387227893157e-05, +-3.58532932124095292024e-05, +-3.61031525361412189944e-05, +-3.63319221736595660043e-05, +-3.65395091497331203439e-05, +-3.67258327814061905970e-05, +-3.68908247021470958485e-05, +-3.70344288788946495372e-05, +-3.71566016220048470271e-05, +-3.72573115881061459097e-05, +-3.73365397758733679086e-05, +-3.73942795147359094356e-05, +-3.74305364465390174970e-05, +-3.74453285001817191228e-05, +-3.74386858592581299020e-05, +-3.74106509227334344111e-05, +-3.73612782586900054964e-05, +-3.72906345511812774523e-05, +-3.71987985402384284698e-05, +-3.70858609550741078051e-05, +-3.69519244405358592356e-05, +-3.67971034768620346741e-05, +-3.66215242927991649845e-05, +-3.64253247721413610217e-05, +-3.62086543537608289011e-05, +-3.59716739251909398806e-05, +-3.57145557098436036985e-05, +-3.54374831479307815388e-05, +-3.51406507711717790501e-05, +-3.48242640713705212661e-05, +-3.44885393629439755150e-05, +-3.41337036395026344345e-05, +-3.37599944245618602615e-05, +-3.33676596164906268116e-05, +-3.29569573277930418366e-05, +-3.25281557188254321234e-05, +-3.20815328260544299979e-05, +-3.16173763849646847373e-05, +-3.11359836477270585640e-05, +-3.06376611957413178553e-05, +-3.01227247471705252121e-05, +-2.95914989595860117668e-05, +-2.90443172278450244467e-05, +-2.84815214773259415084e-05, +-2.79034619526477284249e-05, +-2.73104970020026914545e-05, +-2.67029928572347473455e-05, +-2.60813234097965965382e-05, +-2.54458699827217350983e-05, +-2.47970210987495716533e-05, +-2.41351722447432573014e-05, +-2.34607256325420285845e-05, +-2.27740899563922217575e-05, +-2.20756801471030884767e-05, +-2.13659171230650388217e-05, +-2.06452275383031910749e-05, +-1.99140435276834237366e-05, +-1.91728024494465332597e-05, +-1.84219466252117046706e-05, +-1.76619230776150628139e-05, +-1.68931832657115450086e-05, +-1.61161828183312975558e-05, +-1.53313812655206427630e-05, +-1.45392417682358304494e-05, +-1.37402308464459345215e-05, +-1.29348181058055242533e-05, +-1.21234759630454037166e-05, +-1.13066793702690812049e-05, +-1.04849055382779459772e-05, +-9.65863365911334948940e-06, +-8.82834462796514155621e-06, +-7.99452076460905629502e-06, +-7.15764553453369098759e-06, +-6.31820326991743474922e-06, +-5.47667889061570897704e-06, +-4.63355762531863929758e-06, +-3.78932473303858924915e-06, +-2.94446522508681059839e-06, +-2.09946358769777104725e-06, +-1.25480350545903780141e-06, +-4.10967585703884757521e-07, + 4.31562915977009008788e-07, + 1.27230836894944277571e-06, + 2.11079103932071460005e-06, + 2.94653536014252898618e-06, + 3.77906819987967961097e-06, + 4.60791912899369108820e-06, + 5.43262068449194016279e-06, + 6.25270863229422647450e-06, + 7.06772222727031654239e-06, + 7.87720447080152108251e-06, + 8.68070236573491179038e-06, + 9.47776716855934883059e-06, + 1.02679546387046329188e-05, + 1.10508252847855289948e-05, + 1.18259446076950094435e-05, + 1.25928833403731488022e-05, + 1.33512176841488130493e-05, + 1.41005295415132480126e-05, + 1.48404067452006041290e-05, + 1.55704432834508311935e-05, + 1.62902395213322402135e-05, + 1.69994024180030318645e-05, + 1.76975457398040286305e-05, + 1.83842902690431043002e-05, + 1.90592640083929755197e-05, + 1.97221023807678906147e-05, + 2.03724484245830909945e-05, + 2.10099529842914574005e-05, + 2.16342748960969371002e-05, + 2.22450811687472009364e-05, + 2.28420471593103576108e-05, + 2.34248567438443574510e-05, + 2.39932024828722749476e-05, + 2.45467857815675249479e-05, + 2.50853170445967065243e-05, + 2.56085158254919929746e-05, + 2.61161109705264067420e-05, + 2.66078407569898643540e-05, + 2.70834530258070006151e-05, + 2.75427053084297310910e-05, + 2.79853649479419435960e-05, + 2.84112092143175989727e-05, + 2.88200254137772721131e-05, + 2.92116109921902309310e-05, + 2.95857736324748295058e-05, + 2.99423313459514552895e-05, + 3.02811125576063902359e-05, + 3.06019561852344731414e-05, + 3.09047117124088772445e-05, + 3.11892392552770306917e-05, + 3.14554096231257185974e-05, + 3.17031043727105386106e-05, + 3.19322158563235434462e-05, + 3.21426472635838068469e-05, + 3.23343126569389799764e-05, + 3.25071370008686157485e-05, + 3.26610561847839823827e-05, + 3.27960170396232209987e-05, + 3.29119773481435616428e-05, + 3.30089058489176179569e-05, + 3.30867822340391137381e-05, + 3.31455971405566354542e-05, + 3.31853521356474453628e-05, + 3.32060596955532425618e-05, + 3.32077431783010264656e-05, + 3.31904367902360999997e-05, + 3.31541855463981258254e-05, + 3.30990452247738323123e-05, + 3.30250823144645263966e-05, + 3.29323739578086778848e-05, + 3.28210078865044069620e-05, + 3.26910823517787598727e-05, + 3.25427060486570274289e-05, + 3.23759980343831654933e-05, + 3.21910876410516532862e-05, + 3.19881143825098785360e-05, + 3.17672278555962777865e-05, + 3.15285876357804020743e-05, + 3.12723631672755098660e-05, + 3.09987336476968641276e-05, + 3.07078879073422307631e-05, + 3.04000242831731254834e-05, + 3.00753504875796523151e-05, + 2.97340834720133863225e-05, + 2.93764492855759244065e-05, + 2.90026829286541534467e-05, + 2.86130282016945522135e-05, + 2.82077375492130921937e-05, + 2.77870718991382409868e-05, + 2.73513004975885902525e-05, + 2.69007007391876059731e-05, + 2.64355579930219527422e-05, + 2.59561654243505824063e-05, + 2.54628238121749757804e-05, + 2.49558413627831115046e-05, + 2.44355335193822060570e-05, + 2.39022227679302646662e-05, + 2.33562384393019751726e-05, + 2.27979165078862079359e-05, + 2.22275993867542926926e-05, + 2.16456357195166269815e-05, + 2.10523801689935258924e-05, + 2.04481932028270123260e-05, + 1.98334408761695914203e-05, + 1.92084946115600319473e-05, + 1.85737309761447836221e-05, + 1.79295314563576179442e-05, + 1.72762822302007563351e-05, + 1.66143739372523043473e-05, + 1.59442014465590105223e-05, + 1.52661636225209913461e-05, + 1.45806630889290942863e-05, + 1.38881059912848947536e-05, + 1.31889017575441241904e-05, + 1.24834628574239182218e-05, + 1.17722045604144076358e-05, + 1.10555446926362083376e-05, + 1.03339033926850970682e-05, + 9.60770286660610835401e-06, + 8.87736714213917295769e-06, + 8.14332182237846214528e-06, + 7.40599383898811708220e-06, + 6.66581120511662847053e-06, + 5.92320276815220692627e-06, + 5.17859796246125674333e-06, + 4.43242656225190390784e-06, + 3.68511843470406844027e-06, + 2.93710329350725519965e-06, + 2.18881045294667824256e-06, + 1.44066858267776568184e-06, + 6.93105463328498643878e-07, +-5.34522569318000109946e-08, +-7.98579304717572919173e-07, +-1.54185202251970832288e-06, +-2.28284860840320051088e-06, +-3.02114935421031389665e-06, +-3.75633688210878496775e-06, +-4.48799637936313885382e-06, +-5.21571583119760455970e-06, +-5.93908625161027179838e-06, +-6.65770191203593872154e-06, +-7.37116056769570928293e-06, +-8.07906368153382318078e-06, +-8.78101664560747212731e-06, +-9.47662899980729766419e-06, +-1.01655146477980716876e-05, +-1.08472920700360401147e-05, +-1.15215845337792326716e-05, +-1.21880202999511892778e-05, +-1.28462328267551614196e-05, +-1.34958609699263177819e-05, +-1.41365491795134746316e-05, +-1.47679476930840737262e-05, +-1.53897127252478330606e-05, +-1.60015066533978296873e-05, +-1.66029981995690071228e-05, +-1.71938626083174473280e-05, +-1.77737818205255124692e-05, +-1.83424446430409821820e-05, +-1.88995469140607142496e-05, +-1.94447916641716418988e-05, +-1.99778892729651633619e-05, +-2.04985576211432968317e-05, +-2.10065222380378098066e-05, +-2.15015164444660525898e-05, +-2.19832814908509086081e-05, +-2.24515666905336362430e-05, +-2.29061295482131846272e-05, +-2.33467358834453286897e-05, +-2.37731599491474201167e-05, +-2.41851845450333852378e-05, +-2.45826011259452240434e-05, +-2.49652099050124548756e-05, +-2.53328199515970210081e-05, +-2.56852492839710685329e-05, +-2.60223249566979663422e-05, +-2.63438831426579298076e-05, +-2.66497692096954663589e-05, +-2.69398377918485816931e-05, +-2.72139528551308018016e-05, +-2.74719877578380960005e-05, +-2.77138253053556592794e-05, +-2.79393577994475523249e-05, +-2.81484870820020636713e-05, +-2.83411245732301139656e-05, +-2.85171913042964311541e-05, +-2.86766179443786176822e-05, +-2.88193448221488309965e-05, +-2.89453219416760952935e-05, +-2.90545089927504981216e-05, +-2.91468753556345132793e-05, +-2.92224001002483448552e-05, +-2.92810719798009543599e-05, +-2.93228894188808181459e-05, +-2.93478604960236810328e-05, +-2.93560029207774113129e-05, +-2.93473440052880433669e-05, +-2.93219206304335843936e-05, +-2.92797792065350247323e-05, +-2.92209756286776301080e-05, +-2.91455752266783351279e-05, +-2.90536527097378728982e-05, +-2.89452921058199178666e-05, +-2.88205866958015281636e-05, +-2.86796389424427922371e-05, +-2.85225604142267152093e-05, +-2.83494717041206751521e-05, +-2.81605023433202391432e-05, +-2.79557907100283667510e-05, +-2.77354839333381227289e-05, +-2.74997377922758771290e-05, +-2.72487166100799959093e-05, +-2.69825931437795252883e-05, +-2.67015484691465684885e-05, +-2.64057718610977712947e-05, +-2.60954606696212069907e-05, +-2.57708201913090847589e-05, +-2.54320635365780473264e-05, +-2.50794114926622185510e-05, +-2.47130923824611631432e-05, +-2.43333419193429083098e-05, +-2.39404030579782670638e-05, +-2.35345258413101434184e-05, +-2.31159672437494752078e-05, +-2.26849910106949353332e-05, +-2.22418674944758635930e-05, +-2.17868734868193039472e-05, +-2.13202920479438652059e-05, +-2.08424123323838041491e-05, +-2.03535294116561999106e-05, +-1.98539440938636343103e-05, +-1.93439627403565497755e-05, +-1.88238970795673100412e-05, +-1.82940640181116715769e-05, +-1.77547854492869263538e-05, +-1.72063880590754648210e-05, +-1.66492031297704090782e-05, +-1.60835663413408166554e-05, +-1.55098175706546329380e-05, +-1.49283006886787883053e-05, +-1.43393633557766034665e-05, +-1.37433568152237134072e-05, +-1.31406356850657396885e-05, +-1.25315577484303698698e-05, +-1.19164837424470248790e-05, +-1.12957771458482026110e-05, +-1.06698039654265613285e-05, +-1.00389325214426427445e-05, +-9.40353323211844157182e-06, +-8.76397839734067131087e-06, +-8.12064198169950727862e-06, +-7.47389939698852350989e-06, +-6.82412728429159437049e-06, +-6.17170329578283326645e-06, +-5.51700587636662085001e-06, +-4.86041404527424057491e-06, +-4.20230717776569626185e-06, +-3.54306478703081491720e-06, +-2.88306630643768218789e-06, +-2.22269087224340068095e-06, +-1.56231710689249263685e-06, +-9.02322903026265212716e-07, +-2.43085208325657879777e-07, + 4.15020188692070241853e-07, + 1.07161887179235378480e-06, + 1.72633800896124487047e-06, + 2.37880656301163715107e-06, + 3.02865550076134820403e-06, + 3.67551800066570465779e-06, + 4.31902965876675653769e-06, + 4.95882869287509108695e-06, + 5.59455614484735050385e-06, + 6.22585608085616216224e-06, + 6.85237578953995891761e-06, + 7.47376597792307623553e-06, + 8.08968096499781815715e-06, + 8.69977887286206749402e-06, + 9.30372181530736666231e-06, + 9.90117608375414723029e-06, + 1.04918123304324667667e-05, + 1.10753057487085165546e-05, + 1.16513362504588705059e-05, + 1.22195886403962862164e-05, + 1.27797527872529815987e-05, + 1.33315237917292095805e-05, + 1.38746021511168710365e-05, + 1.44086939205101016335e-05, + 1.49335108705172178858e-05, + 1.54487706413894936150e-05, + 1.59541968934863105428e-05, + 1.64495194539962877323e-05, + 1.69344744598370269687e-05, + 1.74088044966656047203e-05, + 1.78722587339096677364e-05, + 1.83245930557734450217e-05, + 1.87655701881329496747e-05, + 1.91949598212630230727e-05, + 1.96125387283323720589e-05, + 2.00180908796079946171e-05, + 2.04114075523055411008e-05, + 2.07922874360462036562e-05, + 2.11605367338478548244e-05, + 2.15159692586163032817e-05, + 2.18584065250839677179e-05, + 2.21876778371520620508e-05, + 2.25036203706003066312e-05, + 2.28060792511126929382e-05, + 2.30949076276010261842e-05, + 2.33699667407799707231e-05, + 2.36311259869688547377e-05, + 2.38782629770920889936e-05, + 2.41112635908534832393e-05, + 2.43300220260626135784e-05, + 2.45344408430947687194e-05, + 2.47244310044678461521e-05, + 2.48999119095234487111e-05, + 2.50608114242014547006e-05, + 2.52070659059005263759e-05, + 2.53386202234201725390e-05, + 2.54554277719819088525e-05, + 2.55574504833309083937e-05, + 2.56446588309218829473e-05, + 2.57170318301951886415e-05, + 2.57745570339536455825e-05, + 2.58172305228509982138e-05, + 2.58450568910080320990e-05, + 2.58580492267732674574e-05, + 2.58562290886494391582e-05, + 2.58396264764083687885e-05, + 2.58082797974207070447e-05, + 2.57622358282285832381e-05, + 2.57015496713930713401e-05, + 2.56262847076503301675e-05, + 2.55365125434126198959e-05, + 2.54323129536535378888e-05, + 2.53137738202205607126e-05, + 2.51809910656159463322e-05, + 2.50340685822968625073e-05, + 2.48731181575412977117e-05, + 2.46982593939325721589e-05, + 2.45096196255167505238e-05, + 2.43073338296873121584e-05, + 2.40915445348619378086e-05, + 2.38624017240045997246e-05, + 2.36200627340624288075e-05, + 2.33646921513807236321e-05, + 2.30964617031644264128e-05, + 2.28155501450558444859e-05, + 2.25221431449012520778e-05, + 2.22164331627798575491e-05, + 2.18986193273720365431e-05, + 2.15689073087443379398e-05, + 2.12275091876318188378e-05, + 2.08746433212990305033e-05, + 2.05105342060640502609e-05, + 2.01354123365703269947e-05, + 1.97495140618939641253e-05, + 1.93530814385750261550e-05, + 1.89463620806633047968e-05, + 1.85296090068704985814e-05, + 1.81030804849221997979e-05, + 1.76670398732044751401e-05, + 1.72217554598013985296e-05, + 1.67675002990209279609e-05, + 1.63045520455078192621e-05, + 1.58331927860449225669e-05, + 1.53537088691371193265e-05, + 1.48663907324963997689e-05, + 1.43715327285100159978e-05, + 1.38694329478100649496e-05, + 1.33603930410508834665e-05, + 1.28447180389832295180e-05, + 1.23227161709552708244e-05, + 1.17946986819301291035e-05, + 1.12609796481351171312e-05, + 1.07218757914499571946e-05, + 1.01777062926427738516e-05, + 9.62879260356504592831e-06, + 9.07545825840731586903e-06, + 8.51802868414534395823e-06, + 7.95683101026131923061e-06, + 7.39219387787010935662e-06, + 6.82444724835357750922e-06, + 6.25392221161505916386e-06, + 5.68095079406488222078e-06, + 5.10586576644759276318e-06, + 4.52900045162168937197e-06, + 3.95068853240210902949e-06, + 3.37126385957580590002e-06, + 2.79106026020026960787e-06, + 2.21041134629440781136e-06, + 1.62965032403097053739e-06, + 1.04910980353893797621e-06, + 4.69121609423969816268e-07, +-1.09983407885784446779e-07, +-6.87875559861819363080e-07, +-1.26422650655941540912e-06, +-1.83870944215866707785e-06, +-2.41099927925814251037e-06, +-2.98077283181781552669e-06, +-3.54770899664894408157e-06, +-4.11148893334953399492e-06, +-4.67179624258384839990e-06, +-5.22831714261491216074e-06, +-5.78074064397335153019e-06, +-6.32875872218480591626e-06, +-6.87206648846043886310e-06, +-7.41036235823793521568e-06, +-7.94334821749933495355e-06, +-8.47072958676628828367e-06, +-8.99221578268483114820e-06, +-9.50752007711151433478e-06, +-1.00163598536144939110e-05, +-1.05184567613050262248e-05, +-1.10135368659148606880e-05, +-1.15013307980458232298e-05, +-1.19815738984936175071e-05, +-1.24540063605928145280e-05, +-1.29183733694884611521e-05, +-1.33744252382685912655e-05, +-1.38219175408834683421e-05, +-1.42606112417824770782e-05, +-1.46902728222004355977e-05, +-1.51106744030272206920e-05, +-1.55215938641985491263e-05, +-1.59228149605396966692e-05, +-1.63141274340170367916e-05, +-1.66953271223259263928e-05, +-1.70662160637601778752e-05, +-1.74266025983238355662e-05, +-1.77763014650210005691e-05, +-1.81151338952815387428e-05, +-1.84429277024754141470e-05, +-1.87595173674722256573e-05, +-1.90647441202047199617e-05, +-1.93584560171974732774e-05, +-1.96405080150238890778e-05, +-1.99107620396580777466e-05, +-2.01690870516893970240e-05, +-2.04153591073708575137e-05, +-2.06494614154744169461e-05, +-2.08712843899290058163e-05, +-2.10807256982194106203e-05, +-2.12776903055268819069e-05, +-2.14620905145943367527e-05, +-2.16338460013017256061e-05, +-2.17928838459405791773e-05, +-2.19391385601769272338e-05, +-2.20725521096971615139e-05, +-2.21930739325313472097e-05, +-2.23006609530529530257e-05, +-2.23952775916547660337e-05, +-2.24768957701059413827e-05, +-2.25454949125917081373e-05, +-2.26010619424491719610e-05, +-2.26435912746056351556e-05, +-2.26730848037337861828e-05, +-2.26895518881395304210e-05, +-2.26930093293992605151e-05, +-2.26834813477678370105e-05, +-2.26609995533789395977e-05, +-2.26256029132635929800e-05, +-2.25773377142134946906e-05, +-2.25162575215193229503e-05, +-2.24424231336153037980e-05, +-2.23559025326656501465e-05, +-2.22567708311276078921e-05, +-2.21451102143313804113e-05, +-2.20210098791169147888e-05, +-2.18845659685713447666e-05, +-2.17358815029120373732e-05, +-2.15750663065627956596e-05, +-2.14022369314727249265e-05, +-2.12175165767294450026e-05, +-2.10210350045200421447e-05, +-2.08129284524956139116e-05, +-2.05933395425968121279e-05, +-2.03624171863999439073e-05, +-2.01203164870448847703e-05, +-1.98671986378080534994e-05, +-1.96032308173856533286e-05, +-1.93285860819534852074e-05, +-1.90434432540722883950e-05, +-1.87479868085084750535e-05, +-1.84424067550420635135e-05, +-1.81268985183354106028e-05, +-1.78016628149372209476e-05, +-1.74669055274989030828e-05, +-1.71228375762811146975e-05, +-1.67696747880257406472e-05, +-1.64076377622852373006e-05, +-1.60369517352758793533e-05, +-1.56578464413495735093e-05, +-1.52705559721640566414e-05, +-1.48753186336378656238e-05, +-1.44723768007754817841e-05, +-1.40619767704562352530e-05, +-1.36443686122615369144e-05, +-1.32198060174485617084e-05, +-1.27885461461470160532e-05, +-1.23508494728771689751e-05, +-1.19069796304737485969e-05, +-1.14572032525241123438e-05, +-1.10017898143939981797e-05, +-1.05410114729497751473e-05, +-1.00751429050663908628e-05, +-9.60446114501671036024e-06, +-9.12924542083821511740e-06, +-8.64977698977298705156e-06, +-8.16633897287741896158e-06, +-7.67921618889827246499e-06, +-7.18869498751202211574e-06, +-6.69506308202449553879e-06, +-6.19860938162804727016e-06, +-5.69962382331348281457e-06, +-5.19839720353396213883e-06, +-4.69522100971802372742e-06, +-4.19038725172889743185e-06, +-3.68418829336696433132e-06, +-3.17691668401197745318e-06, +-2.66886499050160637978e-06, +-2.16032562934221739981e-06, +-1.65159069934772865291e-06, +-1.14295181480165719692e-06, +-6.34699939237223993940e-07, +-1.27125219930865964068e-07, + 3.79483176804446976763e-07, + 8.84837229415048084051e-07, + 1.38865022392344135295e-06, + 1.89063691565660948537e-06, + 2.39051368980350543056e-06, + 2.88799872070356053645e-06, + 3.38281212979515968504e-06, + 3.87467614211226955731e-06, + 4.36331524126018218350e-06, + 4.84845632277730857507e-06, + 5.32982884579943108584e-06, + 5.80716498294156890627e-06, + 6.28019976832197123205e-06, + 6.74867124362975824505e-06, + 7.21232060217923931738e-06, + 7.67089233085512087109e-06, + 8.12413434987819258522e-06, + 8.57179815031460507597e-06, + 9.01363892925431026452e-06, + 9.44941572258580350576e-06, + 9.87889153529582866875e-06, + 1.03018334692242354077e-05, + 1.07180128482058532928e-05, + 1.11272053405328737749e-05, + 1.15291910786727369798e-05, + 1.19237547761785921742e-05, + 1.23106858417307881825e-05, + 1.26897784902497355293e-05, + 1.30608318510224895531e-05, + 1.34236500727868487704e-05, + 1.37780424257190294344e-05, + 1.41238234002725815088e-05, + 1.44608128028181916441e-05, + 1.47888358480361837552e-05, + 1.51077232480150609343e-05, + 1.54173112980111264947e-05, + 1.57174419588311981054e-05, + 1.60079629357866409767e-05, + 1.62887277541956994331e-05, + 1.65595958313870623361e-05, + 1.68204325451708860712e-05, + 1.70711092987549151222e-05, + 1.73115035820617087312e-05, + 1.75414990294297246641e-05, + 1.77609854736682751155e-05, + 1.79698589964435695681e-05, + 1.81680219749743536840e-05, + 1.83553831250179843454e-05, + 1.85318575401295563383e-05, + 1.86973667271814836071e-05, + 1.88518386381246428555e-05, + 1.89952076979892261869e-05, + 1.91274148291101984921e-05, + 1.92484074715740798728e-05, + 1.93581395998826688587e-05, + 1.94565717358317040323e-05, + 1.95436709576050705363e-05, + 1.96194109050871230563e-05, + 1.96837717813977941246e-05, + 1.97367403506575926565e-05, + 1.97783099319904582180e-05, + 1.98084803897790467670e-05, + 1.98272581201802304074e-05, + 1.98346560339216278375e-05, + 1.98306935353937785049e-05, + 1.98153964980584857704e-05, + 1.97887972361948640476e-05, + 1.97509344730071558156e-05, + 1.97018533051198989033e-05, + 1.96416051634883520843e-05, + 1.95702477707543367439e-05, + 1.94878450950789703635e-05, + 1.93944673004863832040e-05, + 1.92901906937534684103e-05, + 1.91750976678850051373e-05, + 1.90492766422124609142e-05, + 1.89128219991563888266e-05, + 1.87658340176993620855e-05, + 1.86084188036114926950e-05, + 1.84406882164763881947e-05, + 1.82627597935659933724e-05, + 1.80747566706147357355e-05, + 1.78768074995447826664e-05, + 1.76690463631958512617e-05, + 1.74516126871156478269e-05, + 1.72246511484645271060e-05, + 1.69883115820999146554e-05, + 1.67427488838910094079e-05, + 1.64881229113318102759e-05, + 1.62245983815127213317e-05, + 1.59523447665149745417e-05, + 1.56715361862937387256e-05, + 1.53823512991161662699e-05, + 1.50849731896229228884e-05, + 1.47795892545813357618e-05, + 1.44663910864051258596e-05, + 1.41455743545015973133e-05, + 1.38173386845338111450e-05, + 1.34818875356564122405e-05, + 1.31394280758153236577e-05, + 1.27901710551714238936e-05, + 1.24343306777357970924e-05, + 1.20721244712898652016e-05, + 1.17037731556691947766e-05, + 1.13295005094903200078e-05, + 1.09495332354001166718e-05, + 1.05641008239284915968e-05, + 1.01734354160254741075e-05, + 9.77777166436417707733e-06, + 9.37734659349238440105e-06, + 8.97239945891504566951e-06, + 8.56317160519109046130e-06, + 8.14990632312829315351e-06, + 7.73284870615977176810e-06, + 7.31224550598672419900e-06, + 6.88834498757161637657e-06, + 6.46139678356662984916e-06, + 6.03165174826215254474e-06, + 5.59936181114026503485e-06, + 5.16477983011814751843e-06, + 4.72815944456637594131e-06, + 4.28975492818819883339e-06, + 3.84982104183822503198e-06, + 3.40861288638080421604e-06, + 2.96638575565200338164e-06, + 2.52339498962473315831e-06, + 2.07989582785497810255e-06, + 1.63614326329362652845e-06, + 1.19239189654723987055e-06, + 7.48895790669445095407e-07, + 3.05908326571625776241e-07, +-1.36317940881114572753e-07, +-5.77531425986414698518e-07, +-1.01748165446873717438e-06, +-1.45591940480376818372e-06, +-1.89259684853121109570e-06, +-2.32726768946181945073e-06, +-2.75968730172187791391e-06, +-3.18961286654260444098e-06, +-3.61680350772475395115e-06, +-4.04102042570235190153e-06, +-4.46202703013145677961e-06, +-4.87958907093086315863e-06, +-5.29347476770270431638e-06, +-5.70345493746202430210e-06, +-6.10930312060542652779e-06, +-6.51079570505022606116e-06, +-6.90771204847647766264e-06, +-7.29983459860577372710e-06, +-7.68694901145177016447e-06, +-8.06884426747877637565e-06, +-8.44531278560606176982e-06, +-8.81615053499690261524e-06, +-9.18115714457292360416e-06, +-9.54013601019537525608e-06, +-9.89289439945689410725e-06, +-1.02392435540285157503e-05, +-1.05789987895082151180e-05, +-1.09119795927181496489e-05, +-1.12380097164049367058e-05, +-1.15569172712818179387e-05, +-1.18685348153817650919e-05, +-1.21726994406635834228e-05, +-1.24692528568320288901e-05, +-1.27580414723287455134e-05, +-1.30389164724542902805e-05, +-1.33117338945781214641e-05, +-1.35763547004100975057e-05, +-1.38326448452840637915e-05, +-1.40804753444306167702e-05, +-1.43197223362026314689e-05, +-1.45502671422277009592e-05, +-1.47719963244507672032e-05, +-1.49848017390525759050e-05, +-1.51885805872105738001e-05, +-1.53832354626835289546e-05, +-1.55686743961984593867e-05, +-1.57448108966214301034e-05, +-1.59115639888950593595e-05, +-1.60688582487281346781e-05, +-1.62166238340240249699e-05, +-1.63547965130369332254e-05, +-1.64833176892467266300e-05, +-1.66021344229449986304e-05, +-1.67111994495269690472e-05, +-1.68104711944856884120e-05, +-1.68999137851070388113e-05, +-1.69794970588658022861e-05, +-1.70491965685248872658e-05, +-1.71089935839418872147e-05, +-1.71588750905891277256e-05, +-1.71988337847946457871e-05, +-1.72288680657142012447e-05, +-1.72489820240458028352e-05, +-1.72591854275000641512e-05, +-1.72594937030417242213e-05, +-1.72499279159197036566e-05, +-1.72305147455039143491e-05, +-1.72012864579503712398e-05, +-1.71622808757165273689e-05, +-1.71135413439511928759e-05, +-1.70551166937853976150e-05, +-1.69870612025510246137e-05, +-1.69094345509577617692e-05, +-1.68223017772587667151e-05, +-1.67257332284380452606e-05, +-1.66198045084538685654e-05, +-1.65045964235747666643e-05, +-1.63801949248439752678e-05, +-1.62466910477154159362e-05, +-1.61041808488969476394e-05, +-1.59527653404471681951e-05, +-1.57925504211673684571e-05, +-1.56236468053350227754e-05, +-1.54461699488246402123e-05, +-1.52602399726646910730e-05, +-1.50659815840795875837e-05, +-1.48635239950677219589e-05, +-1.46530008385678102385e-05, +-1.44345500822663306819e-05, +-1.42083139401014696147e-05, +-1.39744387815186386459e-05, +-1.37330750385350818741e-05, +-1.34843771106714372927e-05, +-1.32285032678095108182e-05, +-1.29656155510367461763e-05, +-1.26958796715383549959e-05, +-1.24194649075998671690e-05, +-1.21365439997829936740e-05, +-1.18472930443392576808e-05, +-1.15518913849262173693e-05, +-1.12505215026924608397e-05, +-1.09433689047985292748e-05, +-1.06306220114370569618e-05, +-1.03124720414310326811e-05, +-9.98911289646390806746e-06, +-9.66074104402634771841e-06, +-9.32755539913410898457e-06, +-8.98975720490331666607e-06, +-8.64754991204318386249e-06, +-8.30113905734212395051e-06, +-7.95073214121866026069e-06, +-7.59653850440942178638e-06, +-7.23876920386707314615e-06, +-6.87763688794204854321e-06, +-6.51335567091628095621e-06, +-6.14614100697516552689e-06, +-5.77620956367455239778e-06, +-5.40377909498920278296e-06, +-5.02906831401159492038e-06, +-4.65229676537581108160e-06, +-4.27368469748049481391e-06, +-3.89345293458471427688e-06, +-3.51182274885061115744e-06, +-3.12901573240642411555e-06, +-2.74525366950255710500e-06, +-2.36075840884032086628e-06, +-1.97575173612730443720e-06, +-1.59045524696390774673e-06, +-1.20509022010166682739e-06, +-8.19877491164466545524e-07, +-4.35037326897878480005e-07, +-5.07893000186937941852e-08, + 3.32647835264701963937e-07, + 7.15056266991011401958e-07, + 1.09621924837422310365e-06, + 1.47592121985241872538e-06, + 1.85394793018892599705e-06, + 2.23008655655825313813e-06, + 2.60412582354907889203e-06, + 2.97585612102449336496e-06, + 3.34506962075543128396e-06, + 3.71156039179419859137e-06, + 4.07512451449323400283e-06, + 4.43556019312523663384e-06, + 4.79266786703672172316e-06, + 5.14625032027519291555e-06, + 5.49611278963019283487e-06, + 5.84206307102959016220e-06, + 6.18391162423353208402e-06, + 6.52147167576954129561e-06, + 6.85455932005260181654e-06, + 7.18299361864097611125e-06, + 7.50659669756249047314e-06, + 7.82519384267587422464e-06, + 8.13861359300433846395e-06, + 8.44668783199705641891e-06, + 8.74925187666988167100e-06, + 9.04614456457850991435e-06, + 9.33720833857896873390e-06, + 9.62228932933213677251e-06, + 9.90123743550565465295e-06, + 1.01739064016425803086e-05, + 1.04401538936425447330e-05, + 1.06998415718315421479e-05, + 1.09528351615697443715e-05, + 1.11990045213757959499e-05, + 1.14382237085241558977e-05, + 1.16703710420870291280e-05, + 1.18953291633899048006e-05, + 1.21129850938512417829e-05, + 1.23232302901790470909e-05, + 1.25259606968983349296e-05, + 1.27210767961849803022e-05, + 1.29084836549834598316e-05, + 1.30880909693871328668e-05, + 1.32598131062616946208e-05, + 1.34235691420937951136e-05, + 1.35792828990487302932e-05, + 1.37268829782224906786e-05, + 1.38663027900751689578e-05, + 1.39974805820346134686e-05, + 1.41203594632604494623e-05, + 1.42348874265606466504e-05, + 1.43410173674542311574e-05, + 1.44387071003753392044e-05, + 1.45279193720158173131e-05, + 1.46086218718049036649e-05, + 1.46807872395258838879e-05, + 1.47443930700731856367e-05, + 1.47994219153501084768e-05, + 1.48458612833167961215e-05, + 1.48837036341919119975e-05, + 1.49129463738179148723e-05, + 1.49335918441997313264e-05, + 1.49456473112284446691e-05, + 1.49491249496032089275e-05, + 1.49440418249668886146e-05, + 1.49304198732706183515e-05, + 1.49082858773864185118e-05, + 1.48776714409868946381e-05, + 1.48386129597128356167e-05, + 1.47911515896521751179e-05, + 1.47353332131532132959e-05, + 1.46712084019985736114e-05, + 1.45988323779665271851e-05, + 1.45182649708080687578e-05, + 1.44295705736699748613e-05, + 1.43328180959947710691e-05, + 1.42280809139304630388e-05, + 1.41154368182840922366e-05, + 1.39949679600544020416e-05, + 1.38667607935803263323e-05, + 1.37309060173433526632e-05, + 1.35874985124628946476e-05, + 1.34366372789253006354e-05, + 1.32784253695879846650e-05, + 1.31129698220019766261e-05, + 1.29403815880963342583e-05, + 1.27607754617702922906e-05, + 1.25742700044388885011e-05, + 1.23809874685797173814e-05, + 1.21810537193292244224e-05, + 1.19745981541777892090e-05, + 1.17617536208142295677e-05, + 1.15426563331714449024e-05, + 1.13174457857225807409e-05, + 1.10862646660882621001e-05, + 1.08492587659991565309e-05, + 1.06065768906759967075e-05, + 1.03583707666798818434e-05, + 1.01047949482890619580e-05, + 9.84600672246289829138e-06, + 9.58216601244215827264e-06, + 9.31343528005553203603e-06, + 9.03997942678299933766e-06, + 8.76196569363900174996e-06, + 8.47956355993590845071e-06, + 8.19294464098436757177e-06, + 7.90228258480172436834e-06, + 7.60775296787702002085e-06, + 7.30953319006439522813e-06, + 7.00780236866348362574e-06, + 6.70274123175005229701e-06, + 6.39453201082003652993e-06, + 6.08335833281021253502e-06, + 5.76940511155902288967e-06, + 5.45285843877125582177e-06, + 5.13390547455034551393e-06, + 4.81273433756231556671e-06, + 4.48953399489534794848e-06, + 4.16449415167896653590e-06, + 3.83780514052692429906e-06, + 3.50965781086775528301e-06, + 3.18024341822695296120e-06, + 2.84975351352448496748e-06, + 2.51837983245139741199e-06, + 2.18631418498888039782e-06, + 1.85374834513309478132e-06, + 1.52087394088868180660e-06, + 1.18788234459368242750e-06, + 8.54964563638969000998e-07, + 5.22311131639455979077e-07, + 1.90112000130503982774e-07, +-1.41443569165127144841e-07, +-4.72167111427258322109e-07, +-8.01871065130554529929e-07, +-1.13036887767394417904e-06, +-1.45747511019990077643e-06, +-1.78300554152943349745e-06, +-2.10677727116673305869e-06, +-2.42860882131162050769e-06, +-2.74832023782412414206e-06, +-3.06573319008543263771e-06, +-3.38067106969957008626e-06, +-3.69295908798608184869e-06, +-4.00242437219907550613e-06, +-4.30889606043524369669e-06, +-4.61220539516788939752e-06, +-4.91218581536073784053e-06, +-5.20867304711107137976e-06, +-5.50150519277325040547e-06, +-5.79052281851486924603e-06, +-6.07556904025867903059e-06, +-6.35648960796446912367e-06, +-6.63313298820617108662e-06, +-6.90535044500056127508e-06, +-7.17299611884493175119e-06, +-7.43592710392244173663e-06, +-7.69400352343472750019e-06, +-7.94708860302274787185e-06, +-8.19504874223798014101e-06, +-8.43775358402712548757e-06, +-8.67507608219503231826e-06, +-8.90689256681143526513e-06, +-9.13308280752864666172e-06, +-9.35353007477842320907e-06, +-9.56812119881768913406e-06, +-9.77674662659346799308e-06, +-9.97930047640225587741e-06, +-1.01756805903098395061e-05, +-1.03657885843171664226e-05, +-1.05495298962378540402e-05, +-1.07268138312754163948e-05, +-1.08975536052689632541e-05, +-1.10616663855950794401e-05, +-1.12190733297047288709e-05, +-1.13696996212789541697e-05, +-1.15134745039878948566e-05, +-1.16503313128391599354e-05, +-1.17802075031027646805e-05, +-1.19030446768033701643e-05, +-1.20187886067651972661e-05, +-1.21273892582080803395e-05, +-1.22288008078826377517e-05, +-1.23229816607413100770e-05, +-1.24098944641409426887e-05, +-1.24895061195742445941e-05, +-1.25617877919291833080e-05, +-1.26267149162764970278e-05, +-1.26842672021870910226e-05, +-1.27344286355826809563e-05, +-1.27771874781232745640e-05, +-1.28125362641396452218e-05, +-1.28404717951158474197e-05, +-1.28609951317310474550e-05, +-1.28741115834723465414e-05, +-1.28798306958283372134e-05, +-1.28781662350772487912e-05, +-1.28691361706835918807e-05, +-1.28527626553190634970e-05, +-1.28290720025245128650e-05, +-1.27980946620313942489e-05, +-1.27598651927620886218e-05, +-1.27144222335301226119e-05, +-1.26618084714623414664e-05, +-1.26020706081659076143e-05, +-1.25352593236666657602e-05, +-1.24614292381415428035e-05, +-1.23806388714751623682e-05, +-1.22929506006672047076e-05, +-1.21984306151204884824e-05, +-1.20971488698402506546e-05, +-1.19891790365764339750e-05, +-1.18745984529418113659e-05, +-1.17534880695398776456e-05, +-1.16259323951374368445e-05, +-1.14920194399183685165e-05, +-1.13518406568538079223e-05, +-1.12054908812311493295e-05, +-1.10530682683752438347e-05, +-1.08946742296059593923e-05, +-1.07304133664714714479e-05, +-1.05603934032992665185e-05, +-1.03847251181075779763e-05, +-1.02035222719208779302e-05, +-1.00169015365332405226e-05, +-9.82498242076738657132e-06, +-9.62788719526892533595e-06, +-9.42574081589087935042e-06, +-9.21867084571004267567e-06, +-9.00680737572287916197e-06, +-8.79028294427637022824e-06, +-8.56923245527351259271e-06, +-8.34379309521075756921e-06, +-8.11410424909460554577e-06, +-7.88030741528924488369e-06, +-7.64254611934633504094e-06, +-7.40096582686917382960e-06, +-7.15571385546351836380e-06, +-6.90693928582781290984e-06, +-6.65479287203611895166e-06, +-6.39942695106712918212e-06, +-6.14099535163319854876e-06, +-5.87965330236342373891e-06, +-5.61555733939511250274e-06, +-5.34886521342830269742e-06, +-5.07973579629795705422e-06, +-4.80832898711880610677e-06, +-4.53480561805786592893e-06, +-4.25932735978965902460e-06, +-3.98205662668941065763e-06, +-3.70315648181929639785e-06, +-3.42279054176300851270e-06, +-3.14112288136435437299e-06, +-2.85831793842106375632e-06, +-2.57454041839861196264e-06, +-2.28995519920570692832e-06, +-2.00472723609599568439e-06, +-1.71902146674648263972e-06, +-1.43300271656756140053e-06, +-1.14683560429862268911e-06, +-8.60684447942252036623e-07, +-5.74713171094427766504e-07, +-2.89085209713597664617e-07, +-3.96341939478251296110e-09, + 2.80490016808534609067e-07, + 5.64113679962953421250e-07, + 8.46747006173344896037e-07, + 1.12823037680340410583e-06, + 1.40840520793811109215e-06, + 1.68711403904242672689e-06, + 1.96420062076637285675e-06, + 2.23951000184795544334e-06, + 2.51288861506598641053e-06, + 2.78418436219555765417e-06, + 3.05324669791958273155e-06, + 3.31992671265051673821e-06, + 3.58407721421717316118e-06, + 3.84555280837218626654e-06, + 4.10420997807660228022e-06, + 4.35990716151877168199e-06, + 4.61250482882560770565e-06, + 4.86186555742507531383e-06, + 5.10785410601973079235e-06, + 5.35033748713194356707e-06, + 5.58918503818238221671e-06, + 5.82426849106429956731e-06, + 6.05546204017706400874e-06, + 6.28264240888338113098e-06, + 6.50568891435568739365e-06, + 6.72448353077756515444e-06, + 6.93891095087089373919e-06, + 7.14885864570919282062e-06, + 7.35421692279753319929e-06, + 7.55487898238148465092e-06, + 7.75074097196019129528e-06, + 7.94170203897623056888e-06, + 8.12766438165342534124e-06, + 8.30853329796486298722e-06, + 8.48421723269773222391e-06, + 8.65462782259947107971e-06, + 8.81967993958106861606e-06, + 8.97929173195711876623e-06, + 9.13338466370594821242e-06, + 9.28188355172597093559e-06, + 9.42471660107943996656e-06, + 9.56181543820204782021e-06, + 9.69311514206661032516e-06, + 9.81855427328706617540e-06, + 9.93807490115107773816e-06, + 1.00516226285705943843e-05, + 1.01591466149406832020e-05, + 1.02605995968987750983e-05, + 1.03559379069769316912e-05, + 1.04451214901417424743e-05, + 1.05281139182170699055e-05, + 1.06048824021864677416e-05, + 1.06753978023731855288e-05, + 1.07396346364968783339e-05, + 1.07975710856074994448e-05, + 1.08491889978979006982e-05, + 1.08944738903980051003e-05, + 1.09334149485546700144e-05, + 1.09660050237023010909e-05, + 1.09922406284309627094e-05, + 1.10121219298593066863e-05, + 1.10256527408215773174e-05, + 1.10328405089781558080e-05, + 1.10336963038616736523e-05, + 1.10282348018699333952e-05, + 1.10164742692203395746e-05, + 1.09984365428796701980e-05, + 1.09741470094854162102e-05, + 1.09436345822753026573e-05, + 1.09069316760433128688e-05, + 1.08640741801411637853e-05, + 1.08151014295454121441e-05, + 1.07600561740116316219e-05, + 1.06989845453377939037e-05, + 1.06319360227604537122e-05, + 1.05589633965072819227e-05, + 1.04801227295333686110e-05, + 1.03954733174649689091e-05, + 1.03050776467800735478e-05, + 1.02090013512532056038e-05, + 1.01073131666939828753e-05, + 1.00000848840093901980e-05, + 9.88739130062094606394e-06, + 9.76931017026862892453e-06, + 9.64592215123430269373e-06, + 9.51731075301832287069e-06, + 9.38356228150362642153e-06, + 9.24476578264260636546e-06, + 9.10101298470273608427e-06, + 8.95239823910756736568e-06, + 8.79901845991063759865e-06, + 8.64097306194044156673e-06, + 8.47836389765517216299e-06, + 8.31129519274676613631e-06, + 8.13987348053439576051e-06, + 7.96420753518800302127e-06, + 7.78440830382320983472e-06, + 7.60058883750940706770e-06, + 7.41286422123340111201e-06, + 7.22135150286187937354e-06, + 7.02616962114339291517e-06, + 6.82743933279976089379e-06, + 6.62528313874512338812e-06, + 6.41982520947684842004e-06, + 6.21119130968985121773e-06, + 5.99950872215320453294e-06, + 5.78490617089735561883e-06, + 5.56751374375751685266e-06, + 5.34746281431924760940e-06, + 5.12488596331278031701e-06, + 4.89991689950258687289e-06, + 4.67269038011961418454e-06, + 4.44334213087987709952e-06, + 4.21200876564441589159e-06, + 3.97882770575729567648e-06, + 3.74393709911667144121e-06, + 3.50747573902317319374e-06, + 3.26958298285330172902e-06, + 3.03039867060520659957e-06, + 2.79006304336402052000e-06, + 2.54871666173396763366e-06, + 2.30650032428370582201e-06, + 2.06355498605534895103e-06, + 1.82002167717590069487e-06, + 1.57604142162576490206e-06, + 1.33175515621080687286e-06, + 1.08730364977607694810e-06, + 8.42827422715224723608e-07, + 5.98466666817798730862e-07, + 3.54361165500383015065e-07, + 1.10650214466601145526e-07, +-1.32527457159341769654e-07, +-3.75033765181279387019e-07, +-6.16731348117982223764e-07, +-8.57483644384870604974e-07, +-1.09715496882697242401e-06, +-1.33561058856459451812e-06, +-1.57271679809768592289e-06, +-1.80834099364739390638e-06, +-2.04235174667385346287e-06, +-2.27461887654183985059e-06, +-2.50501352229047160599e-06, +-2.73340821346838846000e-06, +-2.95967693999581947631e-06, +-3.18369522101568454449e-06, +-3.40534017269651038867e-06, +-3.62449057495060442016e-06, +-3.84102693703176620771e-06, +-4.05483156197683158547e-06, +-4.26578860985994465493e-06, +-4.47378415981817885059e-06, +-4.67870627082610431870e-06, +-4.88044504117963632650e-06, +-5.07889266666103897304e-06, +-5.27394349735436316360e-06, +-5.46549409308178958515e-06, +-5.65344327743282125745e-06, +-5.83769219035584263823e-06, +-6.01814433929215356056e-06, +-6.19470564881734900520e-06, +-6.36728450877158616566e-06, +-6.53579182085452806356e-06, +-6.70014104365581900433e-06, +-6.86024823610766216613e-06, +-7.01603209933177423939e-06, +-7.16741401686316151218e-06, +-7.31431809323110943569e-06, +-7.45667119087909145226e-06, +-7.59440296540647431485e-06, +-7.72744589911581192265e-06, +-7.85573533285050310242e-06, +-7.97920949610866873263e-06, +-8.09780953542020220872e-06, +-8.21147954097478835185e-06, +-8.32016657148992507269e-06, +-8.42382067730890197923e-06, +-8.52239492171977940256e-06, +-8.61584540048746502295e-06, +-8.70413125959197291938e-06, +-8.78721471116717128705e-06, +-8.86506104763514668932e-06, +-8.93763865403249516855e-06, +-9.00491901852594998912e-06, +-9.06687674111571462719e-06, +-9.12348954052592163661e-06, +-9.17473825928260702616e-06, +-9.22060686698159047512e-06, +-9.26108246174664932824e-06, +-9.29615526988461694400e-06, +-9.32581864373973304274e-06, +-9.35006905775386307602e-06, +-9.36890610273917822759e-06, +-9.38233247837104300938e-06, +-9.39035398390946727946e-06, +-9.39297950715976480397e-06, +-9.39022101168187463889e-06, +-9.38209352226113891724e-06, +-9.36861510865258015606e-06, +-9.34980686761262702199e-06, +-9.32569290323271860845e-06, +-9.29630030559048952147e-06, +-9.26165912773481235900e-06, +-9.22180236102228707016e-06, +-9.17676590882337654416e-06, +-9.12658855861738727770e-06, +-9.07131195249644772880e-06, +-9.01098055609939421230e-06, +-8.94564162599733138977e-06, +-8.87534517555361527068e-06, +-8.80014393928162666969e-06, +-8.72009333572471611652e-06, +-8.63525142888329921994e-06, +-8.54567888821502508222e-06, +-8.45143894723457394103e-06, +-8.35259736074052112995e-06, +-8.24922236069722452712e-06, +-8.14138461080064133836e-06, +-8.02915715975743407074e-06, +-7.91261539330765898304e-06, +-7.79183698502164539547e-06, +-7.66690184590263985908e-06, +-7.53789207282747358732e-06, +-7.40489189585616646447e-06, +-7.26798762444797763775e-06, +-7.12726759261192169612e-06, +-6.98282210303029636403e-06, +-6.83474337018834747465e-06, +-6.68312546254524426573e-06, +-6.52806424378415029071e-06, +-6.36965731317252602944e-06, +-6.20800394507595081702e-06, +-6.04320502765754885186e-06, +-5.87536300080224453186e-06, +-5.70458179330339185380e-06, +-5.53096675935019674964e-06, +-5.35462461435186519118e-06, +-5.17566337014321141424e-06, +-4.99419226960263364762e-06, +-4.81032172072758387396e-06, +-4.62416323020455543279e-06, +-4.43582933651357265599e-06, +-4.24543354260686772332e-06, +-4.05309024820171368161e-06, +-3.85891468172737918331e-06, +-3.66302283196632931856e-06, +-3.46553137942988627687e-06, +-3.26655762750855510455e-06, +-3.06621943343732231445e-06, +-2.86463513911618343607e-06, +-2.66192350182618693409e-06, +-2.45820362488117562057e-06, +-2.25359488825541727446e-06, +-2.04821687922720013799e-06, +-1.84218932307831247064e-06, +-1.63563201388926604866e-06, +-1.42866474546994879804e-06, +-1.22140724246515182631e-06, +-1.01397909167432569799e-06, +-8.06499673625078029042e-07, +-5.99088094436327444290e-07, +-3.91863118017023242330e-07, +-1.84943098628889751524e-07, + 2.15540861419684426667e-08, + 2.27511101966967466315e-07, + 4.32811223880043209387e-07, + 6.37338401859019189379e-07, + 8.40977325854192905002e-07, + 1.04361349022508806704e-06, + 1.24513325755019998089e-06, + 1.44542392177450216890e-06, + 1.64437377065950114052e-06, + 1.84187214750444789869e-06, + 2.03780951209777257423e-06, + 2.23207750087511452161e-06, + 2.42456898624406490649e-06, + 2.61517813504639618351e-06, + 2.80380046612576570131e-06, + 2.99033290696995661509e-06, + 3.17467384939732300976e-06, + 3.35672320425774437633e-06, + 3.53638245511906924553e-06, + 3.71355471091059317744e-06, + 3.88814475749635763264e-06, + 4.06005910814819412596e-06, + 4.22920605290116388692e-06, + 4.39549570675089384069e-06, + 4.55884005668278723919e-06, + 4.71915300750006533998e-06, + 4.87635042643024103849e-06, + 5.03035018648692755928e-06, + 5.18107220856522701196e-06, + 5.32843850224952383525e-06, + 5.47237320531358473132e-06, + 5.61280262189333594894e-06, + 5.74965525931381193962e-06, + 5.88286186355211838841e-06, + 6.01235545332134090329e-06, + 6.13807135275468517243e-06, + 6.25994722267931996977e-06, + 6.37792309046513804878e-06, + 6.49194137843068450202e-06, + 6.60194693079779326846e-06, + 6.70788703918137587323e-06, + 6.80971146660357458814e-06, + 6.90737247002230281208e-06, + 7.00082482136491290685e-06, + 7.09002582705877526905e-06, + 7.17493534605098864026e-06, + 7.25551580631220637360e-06, + 7.33173221981546288786e-06, + 7.40355219598984530240e-06, + 7.47094595364170035832e-06, + 7.53388633134188754210e-06, + 7.59234879627670417821e-06, + 7.64631145156141268828e-06, + 7.69575504201604814413e-06, + 7.74066295840411851953e-06, + 7.78102124013589340075e-06, + 7.81681857643788967132e-06, + 7.84804630599365161535e-06, + 7.87469841505748138885e-06, + 7.89677153404848565748e-06, + 7.91426493262873480251e-06, + 7.92718051327426929855e-06, + 7.93552280334505359466e-06, + 7.93929894566308982874e-06, + 7.93851868760764620798e-06, + 7.93319436873791183408e-06, + 7.92334090695392168925e-06, + 7.90897578320756958670e-06, + 7.89011902477623500857e-06, + 7.86679318711244252764e-06, + 7.83902333428366876954e-06, + 7.80683701801724535304e-06, + 7.77026425536612447970e-06, + 7.72933750501182780370e-06, + 7.68409164222195630977e-06, + 7.63456393248006921998e-06, + 7.58079400380666152174e-06, + 7.52282381779056517397e-06, + 7.46069763935092151688e-06, + 7.39446200525034590259e-06, + 7.32416569138081104189e-06, + 7.24985967884426853560e-06, + 7.17159711885090219710e-06, + 7.08943329645732147265e-06, + 7.00342559317115033967e-06, + 6.91363344844324002262e-06, + 6.82011832007511287137e-06, + 6.72294364356627759040e-06, + 6.62217479042785679954e-06, + 6.51787902548926013278e-06, + 6.41012546322492830867e-06, + 6.29898502313035979733e-06, + 6.18453038417209923617e-06, + 6.06683593834504205765e-06, + 5.94597774336311937993e-06, + 5.82203347451249516448e-06, + 5.69508237570125013232e-06, + 5.56520520973042217313e-06, + 5.43248420782122392469e-06, + 5.29700301842786852943e-06, + 5.15884665536775968036e-06, + 5.01810144530070211867e-06, + 4.87485497458916059279e-06, + 4.72919603557198831207e-06, + 4.58121457228396545999e-06, + 4.43100162565413800605e-06, + 4.27864927821586065842e-06, + 4.12425059836174341351e-06, + 3.96789958417691884638e-06, + 3.80969110688415655311e-06, + 3.64972085393445999985e-06, + 3.48808527177698559195e-06, + 3.32488150834214283460e-06, + 3.16020735527182339492e-06, + 2.99416118993082249565e-06, + 2.82684191723347329501e-06, + 2.65834891131958394095e-06, + 2.48878195711375767025e-06, + 2.31824119180212634826e-06, + 2.14682704626095390252e-06, + 1.97464018646858031233e-06, + 1.80178145494066620423e-06, + 1.62835181221444846777e-06, + 1.45445227842166370380e-06, + 1.28018387498127474226e-06, + 1.10564756644572971662e-06, + 9.30944202533528893967e-07, + 7.56174460383558706575e-07, + 5.81438787057772137935e-07, + 4.06837342332995493781e-07, + 2.32469941807973572217e-07, + 5.84360003605464838908e-08, +-1.15165524016196481795e-07, +-2.88236185961157478515e-07, +-4.60678108053030918551e-07, +-6.32394035641693353382e-07, +-8.03287391175248576365e-07, +-9.73262327992278866677e-07, +-1.14222378354964966348e-06, +-1.31007753205661820651e-06, +-1.47673023648642007660e-06, +-1.64208949993695062100e-06, +-1.80606391631259277593e-06, +-1.96856312029973079598e-06, +-2.12949783660893906853e-06, +-2.28877992845738131554e-06, +-2.44632244526540991875e-06, +-2.60203966954189995785e-06, +-2.75584716293343213363e-06, +-2.90766181141288047594e-06, +-3.05740186958367351418e-06, +-3.20498700407640839933e-06, +-3.35033833601523650274e-06, +-3.49337848253191377853e-06, +-3.63403159730610840275e-06, +-3.77222341011111343188e-06, +-3.90788126534447433042e-06, +-4.04093415952591392912e-06, +-4.17131277773873497690e-06, +-4.29894952900307645335e-06, +-4.42377858055843327302e-06, +-4.54573589104088312044e-06, +-4.66475924253666648223e-06, +-4.78078827150107880212e-06, +-4.89376449852186315914e-06, +-5.00363135691748540988e-06, +-5.11033422015512990528e-06, +-5.21382042807596778544e-06, +-5.31403931191554123584e-06, +-5.41094221810950165016e-06, +-5.50448253087047069913e-06, +-5.59461569353127499173e-06, +-5.68129922864175650784e-06, +-5.76449275681243674909e-06, +-5.84415801429719277657e-06, +-5.92025886930820698860e-06, +-5.99276133705720719759e-06, +-6.06163359351762427620e-06, +-6.12684598790327211872e-06, +-6.18837105385967135374e-06, +-6.24618351936512419082e-06, +-6.30026031533919750782e-06, +-6.35058058295712848316e-06, +-6.39712567966953613306e-06, +-6.43987918392721429004e-06, +-6.47882689861198942782e-06, +-6.51395685317499943250e-06, +-6.54525930448471249620e-06, +-6.57272673638766514792e-06, +-6.59635385798559469776e-06, +-6.61613760063350534395e-06, +-6.63207711366379757420e-06, +-6.64417375884241211495e-06, +-6.65243110356349872368e-06, +-6.65685491279031274194e-06, +-6.65745313974966963219e-06, +-6.65423591538958656902e-06, +-6.64721553660889651050e-06, +-6.63640645326926765439e-06, +-6.62182525400028480084e-06, +-6.60349065080916732668e-06, +-6.58142346250719060277e-06, +-6.55564659696565526196e-06, +-6.52618503221475609801e-06, +-6.49306579639951552747e-06, +-6.45631794660739462695e-06, +-6.41597254658263945040e-06, +-6.37206264334415081952e-06, +-6.32462324272206488792e-06, +-6.27369128383118030161e-06, +-6.21930561249836743221e-06, +-6.16150695366234792122e-06, +-6.10033788276449535378e-06, +-6.03584279615001515287e-06, +-5.96806788049923278545e-06, +-5.89706108130940631553e-06, +-5.82287207044756658384e-06, +-5.74555221279694319542e-06, +-5.66515453201526036843e-06, +-5.58173367543274885226e-06, +-5.49534587810695348729e-06, +-5.40604892606070708310e-06, +-5.31390211872570004752e-06, +-5.21896623061564390400e-06, +-5.12130347225329365013e-06, +-5.02097745037598523939e-06, +-4.91805312744465109411e-06, +-4.81259678048159588907e-06, +-4.70467595926274513780e-06, +-4.59435944389046620792e-06, +-4.48171720177175865495e-06, +-4.36682034403174463086e-06, +-4.24974108138584086476e-06, +-4.13055267949739200956e-06, +-4.00932941385171509125e-06, +-3.88614652417032873467e-06, +-3.76108016839454787432e-06, +-3.63420737626596489757e-06, +-3.50560600253174686132e-06, +-3.37535467980288975763e-06, +-3.24353277109359282678e-06, +-3.11022032207008786392e-06, +-2.97549801303766165317e-06, +-2.83944711069247344591e-06, +-2.70214941967136185736e-06, +-2.56368723392205452038e-06, +-2.42414328792700028154e-06, +-2.28360070780758763959e-06, +-2.14214296233768618929e-06, +-1.99985381389505311643e-06, +-1.85681726937918172971e-06, +-1.71311753112369806511e-06, +-1.56883894783374962087e-06, +-1.42406596557164193617e-06, +-1.27888307882598605392e-06, +-1.13337478168536349648e-06, +-9.87625519151570836163e-07, +-8.41719638613064665786e-07, +-6.95741341511352204364e-07, +-5.49774635225687810111e-07, +-4.03903285203652358387e-07, +-2.58210767364619000791e-07, +-1.12780220802875344963e-07, + 3.23055991830684097878e-08, + 1.76964367708724778855e-07, + 3.21114236543438189078e-07, + 4.64673879946063572873e-07, + 6.07562540071123210426e-07, + 7.49700071920371749061e-07, + 8.91006987815025860095e-07, + 1.03140450136427425456e-06, + 1.17081457090602433941e-06, + 1.30915994239623084851e-06, + 1.44636419172353368897e-06, + 1.58235176642631552541e-06, + 1.71704802678972351765e-06, + 1.85037928630060069746e-06, + 1.98227285143870244472e-06, + 2.11265706078306988520e-06, + 2.24146132341246485419e-06, + 2.36861615658157347906e-06, + 2.49405322264845444755e-06, + 2.61770536524023275885e-06, + 2.73950664463357572141e-06, + 2.85939237233350266468e-06, + 2.97729914483249884479e-06, + 3.09316487653266211920e-06, + 3.20692883181446816197e-06, + 3.31853165623432036477e-06, + 3.42791540683944990220e-06, + 3.53502358157950725138e-06, + 3.63980114780429875857e-06, + 3.74219456983363037592e-06, + 3.84215183558227767505e-06, + 3.93962248223251686305e-06, + 4.03455762093816806731e-06, + 4.12690996055009787897e-06, + 4.21663383035196559137e-06, + 4.30368520179581453395e-06, + 4.38802170922777651609e-06, + 4.46960266959470585012e-06, + 4.54838910112321163730e-06, + 4.62434374096319227585e-06, + 4.69743106178853688561e-06, + 4.76761728734836138144e-06, + 4.83487040696272629773e-06, + 4.89916018895741111830e-06, + 4.96045819303296106926e-06, + 5.01873778156387963061e-06, + 5.07397412982442447456e-06, + 5.12614423513811590729e-06, + 5.17522692494871317675e-06, + 5.22120286381103742548e-06, + 5.26405455930064433061e-06, + 5.30376636684197204255e-06, + 5.34032449345513637005e-06, + 5.37371700042290210606e-06, + 5.40393380487774409700e-06, + 5.43096668031327048978e-06, + 5.45480925602115842708e-06, + 5.47545701545760188074e-06, + 5.49290729354319507956e-06, + 5.50715927290080433390e-06, + 5.51821397903640711657e-06, + 5.52607427446940615412e-06, + 5.53074485181774806004e-06, + 5.53223222584567817618e-06, + 5.53054472448127380454e-06, + 5.52569247881201016526e-06, + 5.51768741206704879188e-06, + 5.50654322759543274221e-06, + 5.49227539585013617960e-06, + 5.47490114038823605808e-06, + 5.45443942289814534188e-06, + 5.43091092726536726806e-06, + 5.40433804268870449940e-06, + 5.37474484585942960917e-06, + 5.34215708221641970028e-06, + 5.30660214629070434828e-06, + 5.26810906115345203946e-06, + 5.22670845698185819179e-06, + 5.18243254875779933987e-06, + 5.13531511311474995156e-06, + 5.08539146434873193589e-06, + 5.03269842960957088606e-06, + 4.97727432328926165021e-06, + 4.91915892062447536855e-06, + 4.85839343053077035771e-06, + 4.79502046768650205761e-06, + 4.72908402388465426040e-06, + 4.66062943867137881228e-06, + 4.58970336929019699759e-06, + 4.51635375995152054556e-06, + 4.44062981044616933641e-06, + 4.36258194412544737627e-06, + 4.28226177526485068410e-06, + 4.19972207583456497138e-06, + 4.11501674169647542961e-06, + 4.02820075825028238263e-06, + 3.93933016554731602391e-06, + 3.84846202289762216335e-06, + 3.75565437298938188386e-06, + 3.66096620554404999308e-06, + 3.56445742052937107578e-06, + 3.46618879095310788465e-06, + 3.36622192525887642755e-06, + 3.26461922935039320666e-06, + 3.16144386826273460570e-06, + 3.05675972750716587302e-06, + 2.95063137411155366322e-06, + 2.84312401738004221383e-06, + 2.73430346939548900412e-06, + 2.62423610528835733665e-06, + 2.51298882329570483720e-06, + 2.40062900463402164141e-06, + 2.28722447320975292833e-06, + 2.17284345519123839340e-06, + 2.05755453846596430753e-06, + 1.94142663200690945903e-06, + 1.82452892517181498007e-06, + 1.70693084695912356741e-06, + 1.58870202524435859482e-06, + 1.46991224602059460634e-06, + 1.35063141266662197534e-06, + 1.23092950526634752769e-06, + 1.11087654000282617921e-06, + 9.90542528650260827215e-07, + 8.69997438187136635693e-07, + 7.49311150553558232788e-07, + 6.28553422575956171735e-07, + 5.07793846080199777306e-07, + 3.87101808219950752071e-07, + 2.66546452036637359768e-07, + 1.46196637279211919523e-07, + 2.61209014996513097622e-08, +-9.36125785480710641559e-08, +-2.12936025188332329408e-07, +-3.31782097760571907408e-07, +-4.50083930191668236211e-07, +-5.67775168183275709294e-07, +-6.84790005993688176635e-07, +-8.01063222793833814618e-07, +-9.16530218579230311038e-07, +-1.03112704961422672079e-06, +-1.14479046339492176093e-06, +-1.25745793310772014899e-06, +-1.36906769156673085052e-06, +-1.47955876461155409369e-06, +-1.58887100394770566988e-06, +-1.69694511941227368702e-06, +-1.80372271064780189541e-06, +-1.90914629816775581196e-06, +-2.01315935379763895325e-06, +-2.11570633047440601331e-06, +-2.21673269139235624129e-06, +-2.31618493847693730396e-06, +-2.41401064017204397923e-06, +-2.51015845853012064279e-06, +-2.60457817558802397410e-06, +-2.69722071901685094830e-06, +-2.78803818703287373008e-06, +-2.87698387255719700099e-06, +-2.96401228661247619401e-06, +-3.04907918094525491427e-06, +-3.13214156986324088414e-06, +-3.21315775127703456810e-06, +-3.29208732693637732224e-06, +-3.36889122185290401895e-06, +-3.44353170289642487268e-06, +-3.51597239656325077098e-06, +-3.58617830590191733468e-06, +-3.65411582659302460743e-06, +-3.71975276217506551713e-06, +-3.78305833841012117849e-06, +-3.84400321678365093078e-06, +-3.90255950713312254181e-06, +-3.95870077940074512301e-06, +-4.01240207450610770714e-06, +-4.06363991433488812364e-06, +-4.11239231084125285599e-06, +-4.15863877425935865654e-06, +-4.20236032042448446743e-06, +-4.24353947720017342875e-06, +-4.28216029001119185047e-06, +-4.31820832648155806497e-06, +-4.35167068017766995946e-06, +-4.38253597345699451516e-06, +-4.41079435942349164690e-06, +-4.43643752299069560910e-06, +-4.45945868105587513408e-06, +-4.47985258178600159821e-06, +-4.49761550302029909350e-06, +-4.51274524979143300062e-06, +-4.52524115097084023650e-06, +-4.53510405504175193850e-06, +-4.54233632500539397060e-06, +-4.54694183242584894293e-06, +-4.54892595061959283142e-06, +-4.54829554699628510261e-06, +-4.54505897455774022598e-06, +-4.53922606256257512138e-06, +-4.53080810636444806448e-06, +-4.51981785643228738179e-06, +-4.50626950656128519675e-06, +-4.49017868128402610519e-06, +-4.47156242249136545128e-06, +-4.45043917527324955132e-06, +-4.42682877299008102390e-06, +-4.40075242158549665903e-06, +-4.37223268315208425070e-06, +-4.34129345876175116439e-06, +-4.30795997057291989114e-06, +-4.27225874322715952063e-06, +-4.23421758454818478526e-06, +-4.19386556555651685739e-06, +-4.15123299981356679695e-06, +-4.10635142210863573125e-06, +-4.05925356650451797034e-06, +-4.00997334375461245165e-06, +-3.95854581810788347368e-06, +-3.90500718351647261954e-06, +-3.84939473926163028560e-06, +-3.79174686501394100978e-06, +-3.73210299534384178129e-06, +-3.67050359369971365087e-06, +-3.60699012586834896589e-06, +-3.54160503293725947090e-06, +-3.47439170377438781006e-06, +-3.40539444704242567051e-06, +-3.33465846276757226665e-06, +-3.26222981347759901722e-06, +-3.18815539492950643052e-06, +-3.11248290644416109035e-06, +-3.03526082086643820009e-06, +-2.95653835416947222251e-06, +-2.87636543472176765438e-06, +-2.79479267223601303066e-06, +-2.71187132641859964837e-06, +-2.62765327533899515464e-06, +-2.54219098353815390706e-06, +-2.45553746989530186833e-06, +-2.36774627527249690158e-06, +-2.27887142995641191922e-06, +-2.18896742091688744107e-06, +-2.09808915890182256402e-06, +-2.00629194538800892082e-06, +-1.91363143940754862785e-06, +-1.82016362426948875164e-06, +-1.72594477419635162234e-06, +-1.63103142089514905451e-06, +-1.53548032008255493308e-06, +-1.43934841798375985031e-06, +-1.34269281782482158857e-06, +-1.24557074633660619018e-06, +-1.14803952029313359972e-06, +-1.05015651309915032019e-06, +-9.51979121449571438300e-07, +-8.53564732078559276071e-07, +-7.54970688617303580583e-07, +-6.56254258580785667422e-07, +-5.57472600498841932364e-07, +-4.58682731214803567250e-07, +-3.59941493366721268602e-07, +-2.61305523070885236846e-07, +-1.62831217825798099669e-07, +-6.45747046531622918148e-08, + 3.34081915028460607542e-08, + 1.31061979105115269233e-07, + 2.28331531061093047517e-07, + 3.25162115452506418290e-07, + 4.21499425940175324931e-07, + 5.17289611827256223732e-07, + 6.12479307764515172907e-07, + 7.07015663081470306902e-07, + 8.00846370727535963142e-07, + 8.93919695807548723643e-07, + 9.86184503696360592316e-07, + 1.07759028771747680805e-06, + 1.16808719637099324993e-06, + 1.25762606009643313325e-06, + 1.34615841755636422783e-06, + 1.43363654142701431353e-06, + 1.52001346368244521319e-06, + 1.60524300035914707475e-06, + 1.68927977578831839769e-06, + 1.77207924628335479643e-06, + 1.85359772327053896192e-06, + 1.93379239585117203927e-06, + 2.01262135278386203690e-06, + 2.09004360387575857427e-06, + 2.16601910077334100819e-06, + 2.24050875713967010219e-06, + 2.31347446821209968128e-06, + 2.38487912972836386475e-06, + 2.45468665621208123303e-06, + 2.52286199861151334042e-06, + 2.58937116127982583862e-06, + 2.65418121829169547439e-06, + 2.71726032908779813765e-06, + 2.77857775344037205028e-06, + 2.83810386573328862561e-06, + 2.89581016855032907358e-06, + 2.95166930556685687487e-06, + 3.00565507373729543829e-06, + 3.05774243477661226693e-06, + 3.10790752592901346437e-06, + 3.15612767002082679062e-06, + 3.20238138479374552623e-06, + 3.24664839151536307337e-06, + 3.28890962286420223838e-06, + 3.32914723008697677049e-06, + 3.36734458942622126102e-06, + 3.40348630781685071737e-06, + 3.43755822785064014868e-06, + 3.46954743200808672055e-06, + 3.49944224615744907365e-06, + 3.52723224232133607687e-06, + 3.55290824071145572597e-06, + 3.57646231103275916171e-06, + 3.59788777305844983311e-06, + 3.61717919647792329573e-06, + 3.63433240001992844556e-06, + 3.64934444985388431064e-06, + 3.66221365727246736405e-06, + 3.67293957565916496310e-06, + 3.68152299674478401627e-06, + 3.68796594615754264255e-06, + 3.69227167827109476069e-06, + 3.69444467035641090999e-06, + 3.69449061604251067923e-06, + 3.69241641809255407447e-06, + 3.68823018050121809172e-06, + 3.68194119992049474706e-06, + 3.67355995642082701168e-06, + 3.66309810359520425440e-06, + 3.65056845801397982505e-06, + 3.63598498803867909083e-06, + 3.61936280200335549955e-06, + 3.60071813577239656246e-06, + 3.58006833968386969076e-06, + 3.55743186488838466342e-06, + 3.53282824909282608752e-06, + 3.50627810171953317514e-06, + 3.47780308849131654283e-06, + 3.44742591545312398587e-06, + 3.41517031244148100487e-06, + 3.38106101601311265410e-06, + 3.34512375184437054455e-06, + 3.30738521661340731931e-06, + 3.26787305937770838069e-06, + 3.22661586245842979003e-06, + 3.18364312184520498148e-06, + 3.13898522713461071050e-06, + 3.09267344101413714559e-06, + 3.04473987830630518563e-06, + 2.99521748458606001315e-06, + 2.94414001438530427212e-06, + 2.89154200899865406331e-06, + 2.83745877390457421898e-06, + 2.78192635581631105178e-06, + 2.72498151937718603862e-06, + 2.66666172351495323772e-06, + 2.60700509747023960325e-06, + 2.54605041651313995614e-06, + 2.48383707736592921508e-06, + 2.42040507334248784649e-06, + 2.35579496922448726218e-06, + 2.29004787588705505843e-06, + 2.22320542469039954603e-06, + 2.15530974165298533032e-06, + 2.08640342142196774357e-06, + 2.01652950105673072815e-06, + 1.94573143364140580303e-06, + 1.87405306174228235695e-06, + 1.80153859072609659169e-06, + 1.72823256195534356335e-06, + 1.65417982587563572154e-06, + 1.57942551501363361584e-06, + 1.50401501689824875799e-06, + 1.42799394692362609795e-06, + 1.35140812116891807883e-06, + 1.27430352919099175392e-06, + 1.19672630680600165567e-06, + 1.11872270887555548908e-06, + 1.04033908211438514454e-06, + 9.61621837932593595614e-07, + 8.82617425331797973857e-07, + 8.03372303868260350135e-07, + 7.23932916698523442543e-07, + 6.44345663725568065214e-07, + 5.64656874857124303848e-07, + 4.84912783394116915736e-07, + 4.05159499563223062539e-07, + 3.25442984208674460614e-07, + 2.45809022658112731786e-07, + 1.66303198777160306628e-07, + 8.69708692272027903669e-08, + 7.85713794072117322522e-09, +-7.09931691716676215865e-08, +-1.49535529268482347680e-07, +-2.27725747365171486868e-07, +-3.05519980848837318375e-07, +-3.82874763706501346521e-07, +-4.59747030453731194650e-07, +-5.36094139750675601478e-07, +-6.11873897692766847291e-07, +-6.87044580763594041777e-07, +-7.61564958437679165913e-07, +-8.35394315421141605512e-07, +-9.08492473518483241836e-07, +-9.80819813113976304058e-07, +-1.05233729425625164956e-06, +-1.12300647733612530584e-06, +-1.19278954334437999738e-06, +-1.26164931370253481165e-06, +-1.32954926965386881663e-06, +-1.39645357120588546386e-06, +-1.46232707561449405058e-06, +-1.52713535540064995902e-06, +-1.59084471589067184708e-06, +-1.65342221227063001310e-06, +-1.71483566614886781052e-06, +-1.77505368161545113680e-06, +-1.83404566079325564072e-06, +-1.89178181887221348355e-06, +-1.94823319862069280282e-06, +-2.00337168436514229084e-06, +-2.05717001543450264187e-06, +-2.10960179906117775394e-06, +-2.16064152273371070425e-06, +-2.21026456599565581941e-06, +-2.25844721168562965249e-06, +-2.30516665661384152826e-06, +-2.35040102167078548251e-06, +-2.39412936136406383631e-06, +-2.43633167277975945574e-06, +-2.47698890396499016471e-06, +-2.51608296172876497540e-06, +-2.55359671885850362846e-06, +-2.58951402074998920553e-06, +-2.62381969144887382413e-06, +-2.65649953910217082780e-06, +-2.68754036081854804860e-06, +-2.71692994693660306132e-06, +-2.74465708470059315127e-06, +-2.77071156134348277634e-06, +-2.79508416657755373943e-06, +-2.81776669449305452715e-06, +-2.83875194486578497579e-06, +-2.85803372387518624004e-06, +-2.87560684423360267943e-06, +-2.89146712472987382482e-06, +-2.90561138918856466730e-06, +-2.91803746484780862573e-06, +-2.92874418015865453993e-06, +-2.93773136200894074995e-06, +-2.94499983237584587605e-06, +-2.95055140441023676853e-06, +-2.95438887795761926909e-06, +-2.95651603451999344031e-06, +-2.95693763166347438543e-06, +-2.95565939687693110985e-06, +-2.95268802088687215850e-06, +-2.94803115043462330338e-06, +-2.94169738052167357241e-06, +-2.93369624612953431959e-06, +-2.92403821342084482528e-06, +-2.91273467042851974806e-06, +-2.89979791724021359437e-06, +-2.88524115568552475564e-06, +-2.86907847853367548813e-06, +-2.85132485820962740443e-06, +-2.83199613503694229294e-06, +-2.81110900501579379722e-06, +-2.78868100714493697984e-06, +-2.76473051029656053377e-06, +-2.73927669965326065288e-06, +-2.71233956271653185119e-06, +-2.68393987489646478775e-06, +-2.65409918469246439721e-06, +-2.62283979847510613493e-06, +-2.59018476487935021233e-06, +-2.55615785881960940799e-06, +-2.52078356513729817673e-06, +-2.48408706189168983184e-06, +-2.44609420330517115589e-06, +-2.40683150237354884389e-06, +-2.36632611315396292482e-06, +-2.32460581274025857810e-06, +-2.28169898293852692147e-06, +-2.23763459165468254892e-06, +-2.19244217400458949748e-06, +-2.14615181316064773556e-06, +-2.09879412094551363500e-06, +-2.05040021818578316432e-06, +-2.00100171483782110160e-06, +-1.95063068989816435785e-06, +-1.89931967111113481318e-06, +-1.84710161448549238660e-06, +-1.79400988363453340540e-06, +-1.74007822895002694472e-06, +-1.68534076662445773069e-06, +-1.62983195753369262521e-06, +-1.57358658599301992021e-06, +-1.51663973839943020132e-06, +-1.45902678177302702247e-06, +-1.40078334221047426768e-06, +-1.34194528326338093541e-06, +-1.28254868425455118572e-06, +-1.22262981854484770803e-06, +-1.16222513176453179750e-06, +-1.10137122001903489497e-06, +-1.04010480808683832089e-06, +-9.78462727617415689625e-07, +-9.16481895344879420621e-07, +-8.54199291329082445989e-07, +-7.91651937236919995967e-07, +-7.28876874676428218509e-07, +-6.65911143596146899220e-07, +-6.02791760762178925358e-07, +-5.39555698325257482511e-07, +-4.76239862490052774988e-07, +-4.12881072298987595103e-07, +-3.49516038541690854304e-07, +-2.86181342804064272744e-07, +-2.22913416666661733927e-07, +-1.59748521064022687018e-07, +-9.67227258185584328684e-08, +-3.38718893582766938970e-08, + 2.87683613695412570172e-08, + 9.11626507777930940099e-08, + 1.53275874301229528026e-07, + 2.15073217829609376242e-07, + 2.76520176901766833620e-07, + 3.37582575650052953442e-07, + 3.98226585485819280378e-07, + 4.58418743513730979390e-07, + 5.18125970668006750755e-07, + 5.77315589558766536398e-07, + 6.35955342019936643428e-07, + 6.94013406349350241498e-07, + 7.51458414232049067549e-07, + 8.08259467337988365555e-07, + 8.64386153585596963575e-07, + 9.19808563062980821321e-07, + 9.74497303597860849836e-07, + 1.02842351597027310336e-06, + 1.08155888875847427063e-06, + 1.13387567281072351305e-06, + 1.18534669533762647095e-06, + 1.23594537361629275206e-06, + 1.28564572830046089292e-06, + 1.33442239633006842733e-06, + 1.38225064343414957853e-06, + 1.42910637622117390762e-06, + 1.47496615385122660710e-06, + 1.51980719928470874307e-06, + 1.56360741010246000211e-06, + 1.60634536889251227715e-06, + 1.64800035319896004223e-06, + 1.68855234502865835288e-06, + 1.72798203991181336901e-06, + 1.76627085551270775016e-06, + 1.80340093978719079100e-06, + 1.83935517868373362992e-06, + 1.87411720338522404077e-06, + 1.90767139708889131071e-06, + 1.94000290132205409853e-06, + 1.97109762179168084047e-06, + 2.00094223376600235736e-06, + 2.02952418698673586018e-06, + 2.05683171011063731075e-06, + 2.08285381467995650348e-06, + 2.10758029862004405122e-06, + 2.13100174926526816907e-06, + 2.15310954591206726866e-06, + 2.17389586189977999014e-06, + 2.19335366621972616361e-06, + 2.21147672465324978376e-06, + 2.22825960043981455305e-06, + 2.24369765447650766928e-06, + 2.25778704505024781826e-06, + 2.27052472710528124541e-06, + 2.28190845104710389511e-06, + 2.29193676108612702237e-06, + 2.30060899312292095007e-06, + 2.30792527217872156528e-06, + 2.31388650937382493307e-06, + 2.31849439845752497517e-06, + 2.32175141189321189097e-06, + 2.32366079650259840000e-06, + 2.32422656867321367902e-06, + 2.32345350913359285878e-06, + 2.32134715730082542021e-06, + 2.31791380520532445909e-06, + 2.31316049099797609704e-06, + 2.30709499204498586449e-06, + 2.29972581761599807363e-06, + 2.29106220117129925082e-06, + 2.28111409225408822216e-06, + 2.26989214799404362660e-06, + 2.25740772422860767231e-06, + 2.24367286624860951035e-06, + 2.22870029917506208745e-06, + 2.21250341797413235839e-06, + 2.19509627711749353150e-06, + 2.17649357989546114511e-06, + 2.15671066739044013289e-06, + 2.13576350711850353347e-06, + 2.11366868134673037600e-06, + 2.09044337509497678252e-06, + 2.06610536382953460056e-06, + 2.04067300085759004675e-06, + 2.01416520443082648289e-06, + 1.98660144456682630719e-06, + 1.95800172959701842290e-06, + 1.92838659245047678824e-06, + 1.89777707668168250577e-06, + 1.86619472225263513379e-06, + 1.83366155107768614062e-06, + 1.80020005234090271963e-06, + 1.76583316759495554916e-06, + 1.73058427565218490126e-06, + 1.69447717727606724807e-06, + 1.65753607968390744685e-06, + 1.61978558087014416989e-06, + 1.58125065376022968674e-06, + 1.54195663020503578884e-06, + 1.50192918482580689152e-06, + 1.46119431871970167741e-06, + 1.41977834303604934816e-06, + 1.37770786243346328062e-06, + 1.33500975842797161234e-06, + 1.29171117264239797330e-06, + 1.24783948996719974604e-06, + 1.20342232164300215316e-06, + 1.15848748827509167059e-06, + 1.11306300279010028919e-06, + 1.06717705334514073476e-06, + 1.02085798619962035772e-06, + 9.74134288559960768089e-07, + 9.27034571407410057516e-07, + 8.79587552319131062115e-07, + 8.31822038292692897728e-07, + 7.83766908584062082816e-07, + 7.35451097569259232492e-07, + 6.86903577639007368221e-07, + 6.38153342137989641187e-07, + 5.89229388356360835835e-07, + 5.40160700585000643775e-07, + 4.90976233243457187642e-07, + 4.41704894091038422500e-07, + 3.92375527528903780770e-07, + 3.43016898004928283419e-07, + 2.93657673529008577219e-07, + 2.44326409308779522962e-07, + 1.95051531514807551777e-07, + 1.45861321184445247206e-07, + 9.67838982725986303713e-08, + 4.78472058599844523217e-08, +-9.21005474744702503668e-10, +-4.94931931086882342167e-08, +-9.78420376464564573501e-08, +-1.45940458001584575920e-07, +-1.93761626279445676683e-07, +-2.41278982453654766505e-07, +-2.88466248828108414775e-07, +-3.35297444276962340684e-07, +-3.81746898255006320598e-07, +-4.27789264571066302430e-07, +-4.73399534917222114972e-07, +-5.18553052146814792709e-07, +-5.63225523294378261140e-07, +-6.07393032330819015965e-07, +-6.51032052647343771201e-07, +-6.94119459261828810033e-07, +-7.36632540741495661135e-07, +-7.78549010835974351873e-07, +-8.19847019815002990540e-07, +-8.60505165505228740834e-07, +-9.00502504020766893004e-07, +-9.39818560182277438796e-07, +-9.78433337620207624330e-07, +-1.01632732855600549368e-06, +-1.05348152325874204263e-06, +-1.08987741917143933322e-06, +-1.12549702970306422209e-06, +-1.16032289268355194760e-06, +-1.19433807847637408471e-06, +-1.22752619774656060195e-06, +-1.25987140888039317136e-06, +-1.29135842505383920910e-06, +-1.32197252094692572073e-06, +-1.35169953910148305289e-06, +-1.38052589591981443812e-06, +-1.40843858730261145449e-06, +-1.43542519392307942238e-06, +-1.46147388613708025001e-06, +-1.48657342852669403075e-06, +-1.51071318407641715728e-06, +-1.53388311798088013959e-06, +-1.55607380108330755062e-06, +-1.57727641294412167073e-06, +-1.59748274453934551225e-06, +-1.61668520058867329841e-06, +-1.63487680151331660552e-06, +-1.65205118502362447400e-06, +-1.66820260733800235944e-06, +-1.68332594403215350657e-06, +-1.69741669052133461662e-06, +-1.71047096217573973425e-06, +-1.72248549407075639464e-06, +-1.73345764037363372509e-06, +-1.74338537336835821088e-06, +-1.75226728212076132235e-06, +-1.76010257078606954751e-06, +-1.76689105656130685063e-06, +-1.77263316728519251133e-06, +-1.77732993868832065915e-06, +-1.78098301129675234904e-06, +-1.78359462699196298197e-06, +-1.78516762523086079262e-06, +-1.78570543892935940332e-06, +-1.78521209001314350987e-06, +-1.78369218463975973750e-06, +-1.78115090809610287207e-06, +-1.77759401937562411090e-06, +-1.77302784543973451412e-06, +-1.76745927516809092517e-06, +-1.76089575300256703723e-06, +-1.75334527228990434716e-06, +-1.74481636832821328595e-06, +-1.73531811112254267233e-06, +-1.72486009785515407010e-06, +-1.71345244507588775535e-06, +-1.70110578061850780769e-06, +-1.68783123524888313502e-06, +-1.67364043405101201273e-06, +-1.65854548755706267844e-06, +-1.64255898262770882562e-06, +-1.62569397308913031908e-06, +-1.60796397013341495032e-06, +-1.58938293248850158598e-06, +-1.56996525636511224694e-06, +-1.54972576518680987152e-06, +-1.52867969911091771475e-06, +-1.50684270434656038082e-06, +-1.48423082227753830000e-06, +-1.46086047839705183582e-06, +-1.43674847106163933866e-06, +-1.41191196007170637922e-06, +-1.38636845508614875617e-06, +-1.36013580387858669546e-06, +-1.33323218044282189100e-06, +-1.30567607295518684662e-06, +-1.27748627160150214245e-06, +-1.24868185627640912946e-06, +-1.21928218416289764874e-06, +-1.18930687719987378282e-06, +-1.15877580944566389195e-06, +-1.12770909434537172875e-06, +-1.09612707191003274157e-06, +-1.06405029581553169958e-06, +-1.03149952042926247822e-06, +-9.98495687772529807701e-07, +-9.65059914426676481838e-07, +-9.31213478390952664649e-07, +-8.96977805900184483883e-07, +-8.62374458209779445916e-07, +-8.27425118357190793336e-07, +-7.92151577906262162004e-07, +-7.56575723683538659993e-07, +-7.20719524513991164460e-07, +-6.84605017964106205270e-07, +-6.48254297100182736997e-07, +-6.11689497269627655389e-07, +-5.74932782912928941364e-07, +-5.38006334414506664360e-07, +-5.00932334998829214645e-07, +-4.63732957681074963406e-07, +-4.26430352278680451037e-07, +-3.89046632491231587593e-07, +-3.51603863057291967577e-07, +-3.14124046993758822385e-07, +-2.76629112926271202933e-07, +-2.39140902517306048575e-07, +-2.01681157999109538668e-07, +-1.64271509818435231461e-07, +-1.26933464399964462611e-07, +-8.96883920351864315859e-08, +-5.25575149034115698627e-08, +-1.55618952314867990895e-08, + 2.12775764013299585065e-08, + 5.79401926069906488081e-08, + 9.44054405745448819568e-08, + 1.30653013292186337421e-07, + 1.66662820599558795692e-07, + 2.02415000063943526019e-07, + 2.37889927675723810546e-07, + 2.73068228356823773127e-07, + 3.07930786275391611075e-07, + 3.42458754964303537689e-07, + 3.76633567235821728614e-07, + 4.10436944888391124100e-07, + 4.43850908200505621429e-07, + 4.76857785206895217304e-07, + 5.09440220752432540740e-07, + 5.41581185319310635908e-07, + 5.73263983623200237778e-07, + 6.04472262974243596559e-07, + 6.35190021398912689916e-07, + 6.65401615518975020092e-07, + 6.95091768183470321082e-07, + 7.24245575851318119156e-07, + 7.52848515719723294374e-07, + 7.80886452596346764020e-07, + 8.08345645511779781934e-07, + 8.35212754069576196438e-07, + 8.61474844531168266227e-07, + 8.87119395633187721666e-07, + 9.12134304134851931249e-07, + 9.36507890093278214952e-07, + 9.60228901864740647514e-07, + 9.83286520829949339681e-07, + 1.00567036584242141413e-06, + 1.02737049739676264377e-06, + 1.04837742151761943520e-06, + 1.06868209336723852610e-06, + 1.08827592057027628516e-06, + 1.10715076625582966250e-06, + 1.12529895181575091329e-06, + 1.14271325937887085896e-06, + 1.15938693400089711674e-06, + 1.17531368556989454737e-06, + 1.19048769042744956491e-06, + 1.20490359270577919489e-06, + 1.21855650538120670311e-06, + 1.23144201104462276445e-06, + 1.24355616238968221938e-06, + 1.25489548241968085992e-06, + 1.26545696437420174112e-06, + 1.27523807137680262633e-06, + 1.28423673580516101703e-06, + 1.29245135838526580120e-06, + 1.29988080701139087871e-06, + 1.30652441529377014066e-06, + 1.31238198083599927004e-06, + 1.31745376324439163689e-06, + 1.32174048187173134272e-06, + 1.32524331329766233412e-06, + 1.32796388854876269223e-06, + 1.32990429006080199844e-06, + 1.33106704838625078829e-06, + 1.33145513865011407038e-06, + 1.33107197675730615317e-06, + 1.32992141535492971224e-06, + 1.32800773955295289713e-06, + 1.32533566240690744947e-06, + 1.32191032016635722368e-06, + 1.31773726729301165080e-06, + 1.31282247125248552902e-06, + 1.30717230708382066220e-06, + 1.30079355175099455860e-06, + 1.29369337828076866856e-06, + 1.28587934969133494247e-06, + 1.27735941271630673508e-06, + 1.26814189132872078392e-06, + 1.25823548006989592576e-06, + 1.24764923718779050332e-06, + 1.23639257759010710187e-06, + 1.22447526561697376243e-06, + 1.21190740763842257076e-06, + 1.19869944448191002670e-06, + 1.18486214369488304102e-06, + 1.17040659164850020835e-06, + 1.15534418548697581979e-06, + 1.13968662492878543633e-06, + 1.12344590392501977927e-06, + 1.10663430218058598693e-06, + 1.08926437654394660522e-06, + 1.07134895227114512445e-06, + 1.05290111416989715657e-06, + 1.03393419762981751439e-06, + 1.01446177954410255975e-06, + 9.94497669129371662775e-07, + 9.74055898649058925340e-07, + 9.53150714046586472362e-07, + 9.31796565494312280840e-07, + 9.10008097864302267693e-07, + 8.87800141127001133190e-07, + 8.65187700683895514984e-07, + 8.42185947640272748656e-07, + 8.18810209024182236434e-07, + 7.95075957957726542799e-07, + 7.70998803786799171281e-07, + 7.46594482175384812077e-07, + 7.21878845170593542560e-07, + 6.96867851244202251346e-07, + 6.71577555317616239466e-07, + 6.46024098775229858276e-07, + 6.20223699473059009471e-07, + 5.94192641748351015229e-07, + 5.67947266436226132378e-07, + 5.41503960899324198661e-07, + 5.14879149076390935720e-07, + 4.88089281555710163631e-07, + 4.61150825679230424805e-07, + 4.34080255683209686411e-07, + 4.06894042881135298369e-07, + 3.79608645894640438035e-07, + 3.52240500938070933540e-07, + 3.24806012162310247429e-07, + 2.97321542063398880870e-07, + 2.69803401961428131034e-07, + 2.42267842555118836346e-07, + 2.14731044557422131870e-07, + 1.87209109417413194962e-07, + 1.59718050133666455064e-07, + 1.32273782164225461408e-07, + 1.04892114438199221113e-07, + 7.75887404739308462697e-08, + 5.03792296086632588358e-08, + 2.32790183440865896232e-08, +-3.69659818658931578941e-09, +-3.05324746267394544896e-08, +-5.72136236741530471848e-08, +-8.37252242245850243792e-08, +-1.10052629376678321428e-07, +-1.36181374294073481367e-07, +-1.62097183920627326452e-07, +-1.87785980544769814165e-07, +-2.13233891209139598521e-07, +-2.38427254961746979659e-07, +-2.63352629945029146904e-07, +-2.87996800319276546365e-07, +-3.12346783017024135980e-07, +-3.36389834325182185351e-07, +-3.60113456291384048568e-07, +-3.83505402952390790727e-07, +-4.06553686380447893525e-07, +-4.29246582545680592520e-07, +-4.51572636991498591533e-07, +-4.73520670320518712649e-07, +-4.95079783488583814637e-07, +-5.16239362904583738092e-07, +-5.36989085333807117288e-07, +-5.57318922603415019422e-07, +-5.77219146106557435187e-07, +-5.96680331105458410703e-07, +-6.15693360830245960493e-07, +-6.34249430372643094367e-07, +-6.52340050373084766760e-07, +-6.69957050499727724785e-07, +-6.87092582718938420602e-07, +-7.03739124355339611445e-07, +-7.19889480941261699077e-07, +-7.35536788854606509566e-07, +-7.50674517744575483077e-07, +-7.65296472744807734602e-07, +-7.79396796473609713033e-07, +-7.92969970821073911788e-07, +-8.06010818523039620686e-07, +-8.18514504521946435161e-07, +-8.30476537114796092696e-07, +-8.41892768888536356313e-07, +-8.52759397443332283837e-07, +-8.63072965904298430121e-07, +-8.72830363222411219091e-07, +-8.82028824265426919197e-07, +-8.90665929699767875244e-07, +-8.98739605664438117104e-07, +-9.06248123238310469019e-07, +-9.13190097701748130089e-07, +-9.19564487594497149126e-07, +-9.25370593571038710503e-07, +-9.30608057055225739965e-07, +-9.35276858695977623270e-07, +-9.39377316625935791305e-07, +-9.42910084525095898317e-07, +-9.45876149491550481034e-07, +-9.48276829721570430580e-07, +-9.50113772001370499672e-07, +-9.51388949013003911569e-07, +-9.52104656456936804630e-07, +-9.52263509993941125969e-07, +-9.51868442009069101583e-07, +-9.50922698200532126112e-07, +-9.49429833996434605628e-07, +-9.47393710802382531800e-07, +-9.44818492083089586131e-07, +-9.41708639281177158997e-07, +-9.38068907576461653450e-07, +-9.33904341489098676729e-07, +-9.29220270330045943147e-07, +-9.24022303502344510841e-07, +-9.18316325656801089995e-07, +-9.12108491705894399878e-07, +-9.05405221699414408662e-07, +-8.98213195565829804566e-07, +-8.90539347723179252958e-07, +-8.82390861563444624379e-07, +-8.73775163814392542299e-07, +-8.64699918782943232475e-07, +-8.55173022484167478071e-07, +-8.45202596660064471297e-07, +-8.34796982692334232859e-07, +-8.23964735413379340429e-07, +-8.12714616819815811869e-07, +-8.01055589692947371830e-07, +-7.88996811130245460602e-07, +-7.76547625992668790471e-07, +-7.63717560271924312522e-07, +-7.50516314382267606353e-07, +-7.36953756381291203872e-07, +-7.23039915124214685738e-07, +-7.08784973356202141615e-07, +-6.94199260747239361661e-07, +-6.79293246874135843310e-07, +-6.64077534154205262483e-07, +-6.48562850735273878957e-07, +-6.32760043346189360169e-07, +-6.16680070113397994562e-07, +-6.00333993346826913225e-07, +-5.83732972300828602773e-07, +-5.66888255913847209443e-07, +-5.49811175532121660261e-07, +-5.32513137621453772346e-07, +-5.15005616471779758539e-07, +-4.97300146899023921939e-07, +-4.79408316948729425562e-07, +-4.61341760605933600647e-07, +-4.43112150515734081304e-07, +-4.24731190718963677602e-07, +-4.06210609407354576801e-07, +-3.87562151702548692569e-07, +-3.68797572463265930466e-07, +-3.49928629124907727258e-07, +-3.30967074575835952180e-07, +-3.11924650074512148172e-07, +-2.92813078211650909737e-07, +-2.73644055921480525304e-07, +-2.54429247546160283934e-07, +-2.35180277957349847825e-07, +-2.15908725738868123295e-07, +-1.96626116434371227810e-07, +-1.77343915863602168094e-07, +-1.58073523511642661593e-07, +-1.38826265993976471359e-07, +-1.19613390601659479034e-07, +-1.00446058929897965640e-07, +-8.13353405935726935918e-08, +-6.22922070331324441674e-08, +-4.33275254142092293362e-08, +-2.44520526242285169324e-08, + 0 /* Need a final zero coefficient */ + diff --git a/libk3b/plugin/libsamplerate/mid_qual_coeffs.h b/libk3b/plugin/libsamplerate/mid_qual_coeffs.h new file mode 100644 index 0000000..7bf47df --- /dev/null +++ b/libk3b/plugin/libsamplerate/mid_qual_coeffs.h @@ -0,0 +1,5315 @@ +/* +** Copyright (C) 2002,2003 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +/* +** f = make_filter (19, 128, 100.2) ; +** Pass band width : 0.0039063 (should be 0.0039062) +** Stop band atten. : 100.35 dB +** -3dB band width : 0.665 +** half length : 5285 +** increment : 128 +*/ + + 9.20381425342432724079e-01, + 9.20302993473144703707e-01, + 9.20067721990720843728e-01, + 9.19675683262634269255e-01, + 9.19126997871811179941e-01, + 9.18421834572361261984e-01, + 9.17560410227629907887e-01, + 9.16542989730570578644e-01, + 9.15369885906517022356e-01, + 9.14041459398341027409e-01, + 9.12558118534084750095e-01, + 9.10920319177104365060e-01, + 9.09128564558774221460e-01, + 9.07183405093831884969e-01, + 9.05085438178449441793e-01, + 9.02835307971073142141e-01, + 9.00433705156164609917e-01, + 8.97881366690907456451e-01, + 8.95179075534992096941e-01, + 8.92327660363587904513e-01, + 8.89327995263616055688e-01, + 8.86180999413433867495e-01, + 8.82887636746086057471e-01, + 8.79448915596223401714e-01, + 8.75865888330860098421e-01, + 8.72139650964099621966e-01, + 8.68271342755988384532e-01, + 8.64262145795659297853e-01, + 8.60113284568922442652e-01, + 8.55826025510500576488e-01, + 8.51401676541053253899e-01, + 8.46841586589208494829e-01, + 8.42147145098761318316e-01, + 8.37319781521271289115e-01, + 8.32360964794223279206e-01, + 8.27272202804994805092e-01, + 8.22055041840814237908e-01, + 8.16711066024966680921e-01, + 8.11241896739414047879e-01, + 8.05649192034131989004e-01, + 7.99934646023336304310e-01, + 7.94099988268876399999e-01, + 7.88146983151028934778e-01, + 7.82077429226948894758e-01, + 7.75893158577014574462e-01, + 7.69596036139359007677e-01, + 7.63187959032822549332e-01, + 7.56670855868614267159e-01, + 7.50046686050942712498e-01, + 7.43317439066910390366e-01, + 7.36485133765944488538e-01, + 7.29551817629036647439e-01, + 7.22519566028118842560e-01, + 7.15390481475825179558e-01, + 7.08166692865972891013e-01, + 7.00850354705043199210e-01, + 6.93443646334978125445e-01, + 6.85948771147587565977e-01, + 6.78367955790895149626e-01, + 6.70703449367723969488e-01, + 6.62957522626846706970e-01, + 6.55132467147013564102e-01, + 6.47230594514182855370e-01, + 6.39254235492288658271e-01, + 6.31205739187853498429e-01, + 6.23087472208794013184e-01, + 6.14901817817740559136e-01, + 6.06651175080214377644e-01, + 5.98337958007979286990e-01, + 5.89964594697926170141e-01, + 5.81533526466822769940e-01, + 5.73047206982255086238e-01, + 5.64508101390120198282e-01, + 5.55918685439004245374e-01, + 5.47281444601789957005e-01, + 5.38598873194839455891e-01, + 5.29873473495091729113e-01, + 5.21107754855426819063e-01, + 5.12304232818644900149e-01, + 5.03465428230393974296e-01, + 4.94593866351407229764e-01, + 4.85692075969380243627e-01, + 4.76762588510854068424e-01, + 4.67807937153435049460e-01, + 4.58830655938690934459e-01, + 4.49833278886094922733e-01, + 4.40818339108329071419e-01, + 4.31788367928309491095e-01, + 4.22745893998278443604e-01, + 4.13693442421281976085e-01, + 4.04633533875401296687e-01, + 3.95568683741051418945e-01, + 3.86501401231698737959e-01, + 3.77434188528326886036e-01, + 3.68369539917981492216e-01, + 3.59309940936731631034e-01, + 3.50257867517365428789e-01, + 3.41215785142159444554e-01, + 3.32186148001037462318e-01, + 3.23171398155436717659e-01, + 3.14173964708215069930e-01, + 3.05196262979898602641e-01, + 2.96240693691587786418e-01, + 2.87309642154843669637e-01, + 2.78405477468841422439e-01, + 2.69530551725107592187e-01, + 2.60687199220140719547e-01, + 2.51877735676207303861e-01, + 2.43104457470603635416e-01, + 2.34369640873684476068e-01, + 2.25675541295929371621e-01, + 2.17024392544335781308e-01, + 2.08418406088417329514e-01, + 1.99859770336071163044e-01, + 1.91350649919593329695e-01, + 1.82893184992099055997e-01, + 1.74489490534610131034e-01, + 1.66141655674062554970e-01, + 1.57851743012483253237e-01, + 1.49621787967589486845e-01, + 1.41453798125033586297e-01, + 1.33349752602548832225e-01, + 1.25311601426208646393e-01, + 1.17341264919035181968e-01, + 1.09440633102170670199e-01, + 1.01611565108827309190e-01, + 9.38558886112234730392e-02, + 8.61753992607110774760e-02, + 7.85718601412871003875e-02, + 7.10470012366834768880e-02, + 6.36025189112217892440e-02, + 5.62400754046094436545e-02, + 4.89612983408535609731e-02, + 4.17677802514581156257e-02, + 3.46610781130688300200e-02, + 2.76427128997189970605e-02, + 2.07141691498255002546e-02, + 1.38768945480800508230e-02, + 7.13229952237052523822e-03, + 4.81756855863834190269e-04, +-6.07339868562557089193e-03, +-1.25318707108654243260e-02, +-1.88924015449200635719e-02, +-2.51537725552469157431e-02, +-3.13148044620756293988e-02, +-3.73743576329800403224e-02, +-4.33313323615558548818e-02, +-4.91846691301275826258e-02, +-5.49333488564130167919e-02, +-6.05763931240776432041e-02, +-6.61128643971268664670e-02, +-7.15418662180770936754e-02, +-7.68625433898662002719e-02, +-8.20740821414635834952e-02, +-8.71757102771481412473e-02, +-9.21666973094307923065e-02, +-9.70463545756019146937e-02, +-1.01814035337895597566e-01, +-1.06469134867262671396e-01, +-1.11011090510758053673e-01, +-1.15439381742549487808e-01, +-1.19753530198565633080e-01, +-1.23953099694804141917e-01, +-1.28037696229327896402e-01, +-1.32006967967990523904e-01, +-1.35860605213926149970e-01, +-1.39598340360859801690e-01, +-1.43219947830287880342e-01, +-1.46725243992595816289e-01, +-1.50114087072177021520e-01, +-1.53386377036633686499e-01, +-1.56542055470133889550e-01, +-1.59581105431021136321e-01, +-1.62503551293762121821e-01, +-1.65309458575341239328e-01, +-1.67998933746201201123e-01, +-1.70572124025848675943e-01, +-1.73029217163238657751e-01, +-1.75370441202067656183e-01, +-1.77596064231102662712e-01, +-1.79706394119684198518e-01, +-1.81701778238549410682e-01, +-1.83582603166114660675e-01, +-1.85349294380384888026e-01, +-1.87002315936635632454e-01, +-1.88542170131047126524e-01, +-1.89969397150449442746e-01, +-1.91284574708360660678e-01, +-1.92488317667500768993e-01, +-1.93581277648966099125e-01, +-1.94564142628253139433e-01, +-1.95437636518337454206e-01, +-1.96202518740000220188e-01, +-1.96859583779614849552e-01, +-1.97409660734602421250e-01, +-1.97853612846778603718e-01, +-1.98192337023800152496e-01, +-1.98426763348949375398e-01, +-1.98557854579480330681e-01, +-1.98586605633759266665e-01, +-1.98514043067442053081e-01, +-1.98341224538922389353e-01, +-1.98069238264312830200e-01, +-1.97699202462185225082e-01, +-1.97232264788348182760e-01, +-1.96669601760900314424e-01, +-1.96012418175829317146e-01, +-1.95261946513421102978e-01, +-1.94419446335739987131e-01, +-1.93486203675455742390e-01, +-1.92463530416288858271e-01, +-1.91352763665352892941e-01, +-1.90155265117664590280e-01, +-1.88872420413116609561e-01, +-1.87505638486184761371e-01, +-1.86056350908662238020e-01, +-1.84526011225710412367e-01, +-1.82916094285511643402e-01, +-1.81228095562823987574e-01, +-1.79463530476726945695e-01, +-1.77623933702856395822e-01, +-1.75710858480429804596e-01, +-1.73725875914355953888e-01, +-1.71670574272733023058e-01, +-1.69546558280039033617e-01, +-1.67355448406313112031e-01, +-1.65098880152636018348e-01, +-1.62778503333212087867e-01, +-1.60395981354360589455e-01, +-1.57952990490720118766e-01, +-1.55451219158974890400e-01, +-1.52892367189410044448e-01, +-1.50278145095599335868e-01, +-1.47610273342536069130e-01, +-1.44890481613516919346e-01, +-1.42120508076075402482e-01, +-1.39302098647282379673e-01, +-1.36437006258713466877e-01, +-1.33526990121390659594e-01, +-1.30573814991000874963e-01, +-1.27579250433698415668e-01, +-1.24545070092789769700e-01, +-1.21473050956605960193e-01, +-1.18364972627860873255e-01, +-1.15222616594794866063e-01, +-1.12047765504399418623e-01, +-1.08842202438021534716e-01, +-1.05607710189640782716e-01, +-1.02346070547107481641e-01, +-9.90590635766376431670e-02, +-9.57484669108492753020e-02, +-9.24160550406251946054e-02, +-8.90635986110882432731e-02, +-8.56928637219669248060e-02, +-8.23056112326309707861e-02, +-7.89035960720733398066e-02, +-7.54885665541076555929e-02, +-7.20622636980560449249e-02, +-6.86264205551892075841e-02, +-6.51827615411845612270e-02, +-6.17330017748623643969e-02, +-5.82788464234569522637e-02, +-5.48219900546751473525e-02, +-5.13641159957934842484e-02, +-4.79068957000384210154e-02, +-4.44519881204940292552e-02, +-4.10010390917734252048e-02, +-3.75556807196898087553e-02, +-3.41175307791583073969e-02, +-3.06881921205520574736e-02, +-2.72692520847377800619e-02, +-2.38622819270072061837e-02, +-2.04688362501167613050e-02, +-1.70904524466470482402e-02, +-1.37286501508831742385e-02, +-1.03849307004176948793e-02, +-7.06077660767133897385e-03, +-3.75765104151932821316e-03, +-4.76997319211794638602e-04, + 2.77976159123423990222e-03, + 6.01122355799481745270e-03, + 9.21600776157955291212e-03, + 1.23927551599897541740e-02, + 1.55401289427332476439e-02, + 1.86568149735395066857e-02, + 2.17415222216296409596e-02, + 2.47929831813923952366e-02, + 2.78099542803314468686e-02, + 3.07912162751492260448e-02, + 3.37355746358383862260e-02, + 3.66418599176616260893e-02, + 3.95089281209001219608e-02, + 4.23356610382612519317e-02, + 4.51209665898422082608e-02, + 4.78637791455433780907e-02, + 5.05630598348475110426e-02, + 5.32177968438652948535e-02, + 5.58270056995735716732e-02, + 5.83897295411673830645e-02, + 6.09050393784494881189e-02, + 6.33720343372027039575e-02, + 6.57898418914746596631e-02, + 6.81576180827297012366e-02, + 7.04745477258180152980e-02, + 7.27398446017178401668e-02, + 7.49527516370186164263e-02, + 7.71125410701128527480e-02, + 7.92185146040738086270e-02, + 8.12700035461998010478e-02, + 8.32663689342140606042e-02, + 8.52070016491116299928e-02, + 8.70913225146551783773e-02, + 8.89187823835221463620e-02, + 9.06888622101164748601e-02, + 9.24010731100602389354e-02, + 9.40549564063880572107e-02, + 9.56500836624715466971e-02, + 9.71860567017110571486e-02, + 9.86625076140278250980e-02, + 1.00079098749209560726e-01, + 1.01435522697153571170e-01, + 1.02731502255068357643e-01, + 1.03966790381692222867e-01, + 1.05141170138599651662e-01, + 1.06254454618664812005e-01, + 1.07306486861763028529e-01, + 1.08297139757793273174e-01, + 1.09226315937109075271e-01, + 1.10093947648453857613e-01, + 1.10899996624498939357e-01, + 1.11644453935089996155e-01, + 1.12327339828307448677e-01, + 1.12948703559463028978e-01, + 1.13508623208143408223e-01, + 1.14007205483430296145e-01, + 1.14444585517425839738e-01, + 1.14820926647215854066e-01, + 1.15136420185409663053e-01, + 1.15391285179401628658e-01, + 1.15585768159497587204e-01, + 1.15720142876065593129e-01, + 1.15794710025859670655e-01, + 1.15809796967682440694e-01, + 1.15765757427549992320e-01, + 1.15662971193527863711e-01, + 1.15501843800413089847e-01, + 1.15282806204434651320e-01, + 1.15006314448161270358e-01, + 1.14672849315791761104e-01, + 1.14282915979024457531e-01, + 1.13837043633692902578e-01, + 1.13335785127364224723e-01, + 1.12779716578100402957e-01, + 1.12169436984582482353e-01, + 1.11505567827804186187e-01, + 1.10788752664543674320e-01, + 1.10019656712822919142e-01, + 1.09198966429570901160e-01, + 1.08327389080707270352e-01, + 1.07405652303864840302e-01, + 1.06434503663973611953e-01, + 1.05414710201933409239e-01, + 1.04347057976597171192e-01, + 1.03232351600300586991e-01, + 1.02071413768162977398e-01, + 1.00865084781397620906e-01, + 9.96142220648654208581e-02, + 9.83196996791074473432e-02, + 9.69824078270985767691e-02, + 9.56032523559593450102e-02, + 9.41831542538692501054e-02, + 9.27230491424269054335e-02, + 9.12238867646961854030e-02, + 8.96866304691910365410e-02, + 8.81122566900391923639e-02, + 8.65017544235756330462e-02, + 8.48561247016157149670e-02, + 8.31763800616522747111e-02, + 8.14635440142294359189e-02, + 7.97186505077449730772e-02, + 7.79427433909263833733e-02, + 7.61368758732360317865e-02, + 7.43021099834537401829e-02, + 7.24395160266886328770e-02, + 7.05501720400689841250e-02, + 6.86351632473627820685e-02, + 6.66955815127786150187e-02, + 6.47325247941935855156e-02, + 6.27470965960619936341e-02, + 6.07404054222478104186e-02, + 5.87135642290347939398e-02, + 5.66676898785539728820e-02, + 5.46039025928778953833e-02, + 5.25233254090291187821e-02, + 5.04270836351378148876e-02, + 4.83163043079990264794e-02, + 4.61921156522659484556e-02, + 4.40556465415169601352e-02, + 4.19080259614387148903e-02, + 3.97503824753536946779e-02, + 3.75838436923350352470e-02, + 3.54095357381316658274e-02, + 3.32285827291374860626e-02, + 3.10421062496353539206e-02, + 2.88512248325339532018e-02, + 2.66570534438272561950e-02, + 2.44607029709929951755e-02, + 2.22632797155504665032e-02, + 2.00658848899928875242e-02, + 1.78696141193047525197e-02, + 1.56755569472778119589e-02, + 1.34847963478305701845e-02, + 1.12984082415343196903e-02, + 9.11746101754993230892e-03, + 6.94301506117043099736e-03, + 4.77612228716621078223e-03, + 2.61782567912160601259e-03, + 4.69158834953931199938e-04, +-1.66885448120184334310e-03, +-3.79520078056328966087e-03, +-5.90887728454510350456e-03, +-8.00889235270581950621e-03, +-1.00942659036281096735e-02, +-1.21640298285631744818e-02, +-1.42172283976795769261e-02, +-1.62529186587560860178e-02, +-1.82701708281667977996e-02, +-2.02680686740044913030e-02, +-2.22457098911984715861e-02, +-2.42022064684845883420e-02, +-2.61366850470883434199e-02, +-2.80482872709881952966e-02, +-2.99361701286294627777e-02, +-3.17995062859638480401e-02, +-3.36374844106955839251e-02, +-3.54493094876133021942e-02, +-3.72342031249025678941e-02, +-3.89914038513265101549e-02, +-4.07201674041748756805e-02, +-4.24197670078825320172e-02, +-4.40894936432238218615e-02, +-4.57286563069958726380e-02, +-4.73365822621031329120e-02, +-4.89126172779674045499e-02, +-5.04561258611889093539e-02, +-5.19664914763842064604e-02, +-5.34431167571409876382e-02, +-5.48854237070259126652e-02, +-5.62928538905927214331e-02, +-5.76648686143374361590e-02, +-5.90009490975559047765e-02, +-6.03005966330638770723e-02, +-6.15633327377404851455e-02, +-6.27886992928659848356e-02, +-6.39762586742271682771e-02, +-6.51255938719669663639e-02, +-6.62363086001636625078e-02, +-6.73080273961252362191e-02, +-6.83403957093936531564e-02, +-6.93330799804545011567e-02, +-7.02857677091563298744e-02, +-7.11981675128459667867e-02, +-7.20700091742300513742e-02, +-7.29010436789823551562e-02, +-7.36910432431144429843e-02, +-7.44398013301399846808e-02, +-7.51471326580581411303e-02, +-7.58128731961966451092e-02, +-7.64368801519491603003e-02, +-7.70190319474562123947e-02, +-7.75592281862732546571e-02, +-7.80573896100858338754e-02, +-7.85134580455219832640e-02, +-7.89273963411314394278e-02, +-7.92991882945930925963e-02, +-7.96288385702248469045e-02, +-7.99163726068679303172e-02, +-8.01618365162299895132e-02, +-8.03652969717648935077e-02, +-8.05268410881816582014e-02, +-8.06465762916719064446e-02, +-8.07246301809524391402e-02, +-8.07611503792237672705e-02, +-8.07563043771459543319e-02, +-8.07102793669422780010e-02, +-8.06232820677405676024e-02, +-8.04955385422673613816e-02, +-8.03272940050135386691e-02, +-8.01188126219958829388e-02, +-7.98703773022373386681e-02, +-7.95822894810978148650e-02, +-7.92548688955872077111e-02, +-7.88884533517974217975e-02, +-7.84833984845913629202e-02, +-7.80400775096937587838e-02, +-7.75588809683271651618e-02, +-7.70402164645424963885e-02, +-7.64845083953963472689e-02, +-7.58921976741284420864e-02, +-7.52637414464975562645e-02, +-7.45996128004335623540e-02, +-7.39003004691712872543e-02, +-7.31663085280282593503e-02, +-7.23981560849959182580e-02, +-7.15963769653113479841e-02, +-7.07615193901859063086e-02, +-6.98941456498595042879e-02, +-6.89948317711622932658e-02, +-6.80641671797573843961e-02, +-6.71027543572484258538e-02, +-6.61112084933319216207e-02, +-6.50901571331780198770e-02, +-6.40402398202278705375e-02, +-6.29621077345897672828e-02, +-6.18564233272276414732e-02, +-6.07238599501278633608e-02, +-5.95651014826367106170e-02, +-5.83808419541620299276e-02, +-5.71717851634284957019e-02, +-5.59386442944868889082e-02, +-5.46821415296654678162e-02, +-5.34030076596649916354e-02, +-5.21019816909916097525e-02, +-5.07798104509243897198e-02, +-4.94372481902171159729e-02, +-4.80750561837304871138e-02, +-4.66940023291949543593e-02, +-4.52948607443019804486e-02, +-4.38784113623226362799e-02, +-4.24454395264523623443e-02, +-4.09967355830820473495e-02, +-3.95330944741913298257e-02, +-3.80553153290659820773e-02, +-3.65642010555344981748e-02, +-3.50605579309238787888e-02, +-3.35451951929296859900e-02, +-3.20189246305989869135e-02, +-3.04825601756209853266e-02, +-2.89369174941192380812e-02, +-2.73828135791425071599e-02, +-2.58210663440446019923e-02, +-2.42524942169475357656e-02, +-2.26779157364765740490e-02, +-2.10981491489598167732e-02, +-1.95140120072784944982e-02, +-1.79263207715556205368e-02, +-1.63358904118689959861e-02, +-1.47435340131725541729e-02, +-1.31500623826066934119e-02, +-1.15562836593809201841e-02, +-9.96300292740478522779e-03, +-8.37102183084635804999e-03, +-6.78113819279113280714e-03, +-5.19414563717416049443e-03, +-3.61083321415951816885e-03, +-2.03198502912982836496e-03, +-4.58379875457016528785e-04, + 1.10920912878408159559e-03, + 2.67001489999788748156e-03, + 4.22327674398739229267e-03, + 5.76824070645192907292e-03, + 7.30415991891262585123e-03, + 8.83029493991307340428e-03, + 1.03459140913472139728e-02, + 1.18502937897689078484e-02, + 1.33427188725394711699e-02, + 1.48224829186761088151e-02, + 1.62888885642629918649e-02, + 1.77412478122899279487e-02, + 1.91788823367922064977e-02, + 2.06011237811589489888e-02, + 2.20073140504912223570e-02, + 2.33968055978847275234e-02, + 2.47689617045220474012e-02, + 2.61231567534600458980e-02, + 2.74587764969989392427e-02, + 2.87752183175302503337e-02, + 3.00718914817559267172e-02, + 3.13482173881795972425e-02, + 3.26036298077741898416e-02, + 3.38375751177299316508e-02, + 3.50495125281968383790e-02, + 3.62389143019323234363e-02, + 3.74052659667742509741e-02, + 3.85480665208594169835e-02, + 3.96668286305130596281e-02, + 4.07610788207384555637e-02, + 4.18303576582400582495e-02, + 4.28742199269152648999e-02, + 4.38922347957571498678e-02, + 4.48839859791098777508e-02, + 4.58490718892284668251e-02, + 4.67871057810912635566e-02, + 4.76977158894239181008e-02, + 4.85805455578927625204e-02, + 4.94352533604324947958e-02, + 5.02615132146747092823e-02, + 5.10590144874505449946e-02, + 5.18274620923405288098e-02, + 5.25665765792536696099e-02, + 5.32760942160161940495e-02, + 5.39557670619600152073e-02, + 5.46053630334999498541e-02, + 5.52246659616954863048e-02, + 5.58134756417962285546e-02, + 5.63716078747732926568e-02, + 5.68988945008435942352e-02, + 5.73951834249974424118e-02, + 5.78603386345437897820e-02, + 5.82942402086913807890e-02, + 5.86967843201876629533e-02, + 5.90678832290408364902e-02, + 5.94074652683551154841e-02, + 5.97154748223121395467e-02, + 5.99918722963358186373e-02, + 6.02366340794795798730e-02, + 6.04497524990822918123e-02, + 6.06312357677402588574e-02, + 6.07811079226447462109e-02, + 6.08994087573431347460e-02, + 6.09861937459786132565e-02, + 6.10415339600735781800e-02, + 6.10655159779199541159e-02, + 6.10582417866455048894e-02, + 6.10198286770287368075e-02, + 6.09504091311373757955e-02, + 6.08501307028684462752e-02, + 6.07191558914731074892e-02, + 6.05576620081493127712e-02, + 6.03658410357920463540e-02, + 6.01438994819913433365e-02, + 5.98920582253712890930e-02, + 5.96105523553696475814e-02, + 5.92996310055547357076e-02, + 5.89595571805846263569e-02, + 5.85906075769135961662e-02, + 5.81930723973530239501e-02, + 5.77672551595985947492e-02, + 5.73134724988377947108e-02, + 5.68320539645518138516e-02, + 5.63233418116318024227e-02, + 5.57876907859301829351e-02, + 5.52254679043691909524e-02, + 5.46370522297332239514e-02, + 5.40228346402717510277e-02, + 5.33832175942438452720e-02, + 5.27186148895339920517e-02, + 5.20294514184751963337e-02, + 5.13161629180133513350e-02, + 5.05791957153526455793e-02, + 4.98190064692186004858e-02, + 4.90360619068817560340e-02, + 4.82308385570846126500e-02, + 4.74038224790149093080e-02, + 4.65555089874726130139e-02, + 4.56864023743756911267e-02, + 4.47970156267560870589e-02, + 4.38878701413918104191e-02, + 4.29594954362301426065e-02, + 4.20124288587509150950e-02, + 4.10472152914242438548e-02, + 4.00644068544164441703e-02, + 3.90645626056996611575e-02, + 3.80482482387188569728e-02, + 3.70160357777762072384e-02, + 3.59685032712854929615e-02, + 3.49062344830574772248e-02, + 3.38298185817733007563e-02, + 3.27398498288028888537e-02, + 3.16369272645302956892e-02, + 3.05216543933420694779e-02, + 2.93946388674391281826e-02, + 2.82564921696314662325e-02, + 2.71078292952747976208e-02, + 2.59492684335090040282e-02, + 2.47814306479556094309e-02, + 2.36049395570361274233e-02, + 2.24204210140672086093e-02, + 2.12285027872915685321e-02, + 2.00298142400041241651e-02, + 1.88249860109280658937e-02, + 1.76146496949991550329e-02, + 1.63994375247131611573e-02, + 1.51799820521929199751e-02, + 1.39569158321288973312e-02, + 1.27308711057459132687e-02, + 1.15024794859493635635e-02, + 1.02723716438034538834e-02, + 9.04117699648874194318e-03, + 7.80952339689281599400e-03, + 6.57803682497710377058e-03, + 5.34734108107065390925e-03, + 4.11805748123311807923e-03, + 2.89080455483250748500e-03, + 1.66619774448026097997e-03, + 4.44849108462394484276e-04, +-7.72632974192619353775e-04, +-1.98564409587129479459e-03, +-3.19358410962515939027e-03, +-4.39585741537518604610e-03, +-5.59187324294384193596e-03, +-6.78104593178024354222e-03, +-7.96279520725374188872e-03, +-9.13654645338901789942e-03, +-1.03017309819179135599e-02, +-1.14577862975281108415e-02, +-1.26041563591888523127e-02, +-1.37402918374362748022e-02, +-1.48656503675044012608e-02, +-1.59796967981878784704e-02, +-1.70819034363291870349e-02, +-1.81717502868205364741e-02, +-1.92487252880175659098e-02, +-2.03123245424604338683e-02, +-2.13620525428040268501e-02, +-2.23974223928605567502e-02, +-2.34179560236593246880e-02, +-2.44231844044319607034e-02, +-2.54126477484353970049e-02, +-2.63858957135253285875e-02, +-2.73424875973971651111e-02, +-2.82819925274152735029e-02, +-2.92039896449517132060e-02, +-3.01080682841611060874e-02, +-3.09938281451182656712e-02, +-3.18608794612527251866e-02, +-3.27088431610126698090e-02, +-3.35373510236956218211e-02, +-3.43460458293886189418e-02, +-3.51345815029584646050e-02, +-3.59026232520415142235e-02, +-3.66498476989806504234e-02, +-3.73759430066653228208e-02, +-3.80806089982259413085e-02, +-3.87635572705481989964e-02, +-3.94245113015637763110e-02, +-4.00632065512871449187e-02, +-4.06793905565660182666e-02, +-4.12728230195161804872e-02, +-4.18432758896181006270e-02, +-4.23905334394521562946e-02, +-4.29143923340550431655e-02, +-4.34146616938810431252e-02, +-4.38911631513571320884e-02, +-4.43437309010235244933e-02, +-4.47722117432520008706e-02, +-4.51764651215424140052e-02, +-4.55563631533957985598e-02, +-4.59117906547691981278e-02, +-4.62426451581186420681e-02, +-4.65488369240420196693e-02, +-4.68302889465325583584e-02, +-4.70869369518625499604e-02, +-4.73187293911136036551e-02, +-4.75256274263797934276e-02, +-4.77076049106652452791e-02, +-4.78646483615089088359e-02, +-4.79967569283660938639e-02, +-4.81039423537813551346e-02, +-4.81862289283918193705e-02, +-4.82436534398009986280e-02, +-4.82762651153660765635e-02, +-4.82841255589469900422e-02, +-4.82673086816636301433e-02, +-4.82259006267171733140e-02, +-4.81599996883273831494e-02, +-4.80697162248445095112e-02, +-4.79551725660972635867e-02, +-4.78165029150386111656e-02, +-4.76538532437557615928e-02, +-4.74673811839129988766e-02, +-4.72572559116971463444e-02, +-4.70236580273407853148e-02, +-4.67667794292976057857e-02, +-4.64868231831488537553e-02, +-4.61840033853220879867e-02, +-4.58585450217043055776e-02, +-4.55106838212354786188e-02, +-4.51406661045703067048e-02, +-4.47487486278967949715e-02, +-4.43351984220053674246e-02, +-4.39002926267011706063e-02, +-4.34443183206557337339e-02, +-4.29675723467968784242e-02, +-4.24703611333365343983e-02, +-4.19530005105376649355e-02, +-4.14158155233245728333e-02, +-4.08591402398425090903e-02, +-4.02833175560728118381e-02, +-3.96886989966125647289e-02, +-3.90756445117304562764e-02, +-3.84445222708086342678e-02, +-3.77957084522856853748e-02, +-3.71295870302152039577e-02, +-3.64465495575560030628e-02, +-3.57469949463106728693e-02, +-3.50313292446328208851e-02, +-3.42999654110217877534e-02, +-3.35533230857262762536e-02, +-3.27918283594781714840e-02, +-3.20159135396808763874e-02, +-3.12260169141751545152e-02, +-3.04225825127068701115e-02, +-2.96060598662241068746e-02, +-2.87769037641279583351e-02, +-2.79355740096046620269e-02, +-2.70825351731674365818e-02, +-2.62182563445339765484e-02, +-2.53432108829716763732e-02, +-2.44578761662360491536e-02, +-2.35627333382326387134e-02, +-2.26582670555346976649e-02, +-2.17449652328813719526e-02, +-2.08233187877915476571e-02, +-1.98938213844193738378e-02, +-1.89569691767836438767e-02, +-1.80132605515005567165e-02, +-1.70631958701489179486e-02, +-1.61072772113989640119e-02, +-1.51460081130329674015e-02, +-1.41798933139869222375e-02, +-1.32094384965426719925e-02, +-1.22351500287977872639e-02, +-1.12575347075429474386e-02, +-1.02770995016708190789e-02, +-9.29435129624720662855e-03, +-8.30979663736668323903e-03, +-7.32394147791955510418e-03, +-6.33729092439597792991e-03, +-5.35034898484767259402e-03, +-4.36361831813259892082e-03, +-3.37759998456233596562e-03, +-2.39279319807447028376e-03, +-1.40969508004874419758e-03, +-4.28800414884481764701e-04, + 5.49398592542026499921e-04, + 1.52441255742493384819e-03, + 2.49575515346705124192e-03, + 3.46294334909421361660e-03, + 4.42549764133481383921e-03, + 5.38294228725484918269e-03, + 6.33480553283812409388e-03, + 7.28061983920614500670e-03, + 8.21992210606954480656e-03, + 9.15225389230991427658e-03, + 1.00771616335884814375e-02, + 1.09941968568804098599e-02, + 1.19029163918370119862e-02, + 1.28028825788794285712e-02, + 1.36936634739278067369e-02, + 1.45748330496734655737e-02, + 1.54459713933036285605e-02, + 1.63066649005877105372e-02, + 1.71565064662418664820e-02, + 1.79950956704824222010e-02, + 1.88220389616893905849e-02, + 1.96369498350979915235e-02, + 2.04394490074384753420e-02, + 2.12291645874509368741e-02, + 2.20057322421993752093e-02, + 2.27687953591133446229e-02, + 2.35180052036899414625e-02, + 2.42530210727860510989e-02, + 2.49735104434401083973e-02, + 2.56791491171582640651e-02, + 2.63696213596067048635e-02, + 2.70446200356534542653e-02, + 2.77038467397033236206e-02, + 2.83470119212748915272e-02, + 2.89738350057704117935e-02, + 2.95840445103900430424e-02, + 3.01773781551470283990e-02, + 3.07535829689405612597e-02, + 3.13124153906489052779e-02, + 3.18536413652031544230e-02, + 3.23770364346098321606e-02, + 3.28823858238901367557e-02, + 3.33694845219050725826e-02, + 3.38381373570426913222e-02, + 3.42881590677418662816e-02, + 3.47193743678329280744e-02, + 3.51316180066747196786e-02, + 3.55247348240743179848e-02, + 3.58985797999757036414e-02, + 3.62530180989057912444e-02, + 3.65879251091717136446e-02, + 3.69031864768026920953e-02, + 3.71986981342348130286e-02, + 3.74743663237384755371e-02, + 3.77301076155911810361e-02, + 3.79658489210015839821e-02, + 3.81815274997910139576e-02, + 3.83770909628457501661e-02, + 3.85524972693506232102e-02, + 3.87077147188212219997e-02, + 3.88427219379517477127e-02, + 3.89575078623010107037e-02, + 3.90520717128378727634e-02, + 3.91264229673738417326e-02, + 3.91805813269093319851e-02, + 3.92145766769267448137e-02, + 3.92284490436606639308e-02, + 3.92222485453833716318e-02, + 3.91960353387427393179e-02, + 3.91498795601925853038e-02, + 3.90838612625587153437e-02, + 3.89980703467861372635e-02, + 3.88926064889137598768e-02, + 3.87675790623278684888e-02, + 3.86231070553441427351e-02, + 3.84593189841744911850e-02, + 3.82763528013330134314e-02, + 3.80743557995419576456e-02, + 3.78534845111941978257e-02, + 3.76139046034402041441e-02, + 3.73557907689583551525e-02, + 3.70793266124797640804e-02, + 3.67847045331337260676e-02, + 3.64721256026843687614e-02, + 3.61417994397318920186e-02, + 3.57939440799517269443e-02, + 3.54287858424472551500e-02, + 3.50465591922946295700e-02, + 3.46475065993586336943e-02, + 3.42318783934602438590e-02, + 3.37999326159794388769e-02, + 3.33519348679760310739e-02, + 3.28881581549163512501e-02, + 3.24088827280907126882e-02, + 3.19143959228117141125e-02, + 3.14049919934835039537e-02, + 3.08809719456320137809e-02, + 3.03426433649902835277e-02, + 2.97903202437320435703e-02, + 2.92243228039485228309e-02, + 2.86449773184645310742e-02, + 2.80526159290918272737e-02, + 2.74475764624171579553e-02, + 2.68302022432251076334e-02, + 2.62008419056547099679e-02, + 2.55598492021924458828e-02, + 2.49075828106016076979e-02, + 2.42444061388931500489e-02, + 2.35706871284384854304e-02, + 2.28867980553310382263e-02, + 2.21931153300989475463e-02, + 2.14900192958749729211e-02, + 2.07778940251304410081e-02, + 2.00571271150767407865e-02, + 1.93281094818433703264e-02, + 1.85912351535375483524e-02, + 1.78469010622939669442e-02, + 1.70955068354214992365e-02, + 1.63374545857532041393e-02, + 1.55731487013095522970e-02, + 1.48029956343801779445e-02, + 1.40274036901342491479e-02, + 1.32467828148644800601e-02, + 1.24615443839752523814e-02, + 1.16721009898197274068e-02, + 1.08788662294939664221e-02, + 1.00822544926967554851e-02, + 9.28268074975848594965e-03, + 8.48056033994836096224e-03, + 7.67630876016376067356e-03, + 6.87034145410842303492e-03, + 6.06307360206417237519e-03, + 5.25491991135924960826e-03, + 4.44629440763854959229e-03, + 3.63761022703795386390e-03, + 2.82927940936458007654e-03, + 2.02171269238637712692e-03, + 1.21531930732854268409e-03, + 4.10506775680379075531e-04, +-3.92319292591773477897e-04, +-1.19275539932616717227e-03, +-1.99040035684389668771e-03, +-2.78485548493010359392e-03, +-3.57572480602225085608e-03, +-4.36261523851058825862e-03, +-5.14513678806150041162e-03, +-5.92290273686880194143e-03, +-6.69552983074627079685e-03, +-7.46263846397084845696e-03, +-8.22385286178995214557e-03, +-8.97880126050735853649e-03, +-9.72711608506233310623e-03, +-1.04684341240196421979e-02, +-1.12023967018896625919e-02, +-1.19286498486973670946e-02, +-1.26468444667234853479e-02, +-1.33566364943390990250e-02, +-1.40576870668614704873e-02, +-1.47496626743549175825e-02, +-1.54322353163073335003e-02, +-1.61050826531120676310e-02, +-1.67678881542855998110e-02, +-1.74203412433571909468e-02, +-1.80621374393645714451e-02, +-1.86929784948938332301e-02, +-1.93125725306022809347e-02, +-1.99206341661660978060e-02, +-2.05168846475965727105e-02, +-2.11010519708690891250e-02, +-2.16728710018125117487e-02, +-2.22320835922093923420e-02, +-2.27784386920556920775e-02, +-2.33116924579366280312e-02, +-2.38316083574713066806e-02, +-2.43379572697852361585e-02, +-2.48305175819705514773e-02, +-2.53090752814938702020e-02, +-2.57734240445178890144e-02, +-2.62233653201022591517e-02, +-2.66587084102499136118e-02, +-2.70792705457725754736e-02, +-2.74848769579453880429e-02, +-2.78753609459266790682e-02, +-2.82505639399193153594e-02, +-2.86103355600531468472e-02, +-2.89545336709700236455e-02, +-2.92830244320940215330e-02, +-2.95956823435738237971e-02, +-2.98923902878850261677e-02, +-3.01730395670819218079e-02, +-3.04375299356923270655e-02, +-3.06857696292481205158e-02, +-3.09176753884519220361e-02, +-3.11331724789744579418e-02, +-3.13321947068878961518e-02, +-3.15146844297364905896e-02, +-3.16805925632501414468e-02, +-3.18298785837100445262e-02, +-3.19625105259753808373e-02, +-3.20784649771835711496e-02, +-3.21777270661380843109e-02, +-3.22602904484012090180e-02, +-3.23261572871092819903e-02, +-3.23753382295313973938e-02, +-3.24078523793953007792e-02, +-3.24237272650036850719e-02, +-3.24229988031694352224e-02, +-3.24057112589975146455e-02, +-3.23719172015455164404e-02, +-3.23216774553950619842e-02, +-3.22550610481695601561e-02, +-3.21721451540349229203e-02, +-3.20730150332222269105e-02, +-3.19577639676131355917e-02, +-3.18264931924307492572e-02, +-3.16793118240798893259e-02, +-3.15163367841841124406e-02, +-3.13376927198667984409e-02, +-3.11435119203261716325e-02, +-3.09339342297566856355e-02, +-3.07091069566692957682e-02, +-3.04691847796660503223e-02, +-3.02143296497258302680e-02, +-2.99447106890591077666e-02, +-2.96605040865920502324e-02, +-2.93618929901409558836e-02, +-2.90490673953408620744e-02, +-2.87222240313914564669e-02, +-2.83815662436870431995e-02, +-2.80273038733983362314e-02, +-2.76596531340728875314e-02, +-2.72788364853265505316e-02, +-2.68850825036951179836e-02, +-2.64786257507202589523e-02, +-2.60597066383420963853e-02, +-2.56285712916748155410e-02, +-2.51854714092403474124e-02, +-2.47306641207374125480e-02, +-2.42644118424243347698e-02, +-2.37869821301946587910e-02, +-2.32986475304263404573e-02, +-2.27996854286841091342e-02, +-2.22903778963591883699e-02, +-2.17710115353269804961e-02, +-2.12418773207074841614e-02, +-2.07032704418132450230e-02, +-2.01554901413684046940e-02, +-1.95988395530860316784e-02, +-1.90336255376889230961e-02, +-1.84601585174617617569e-02, +-1.78787523094215382302e-02, +-1.72897239571940322667e-02, +-1.66933935616846752803e-02, +-1.60900841106333160335e-02, +-1.54801213071404045879e-02, +-1.48638333972560768986e-02, +-1.42415509967192804169e-02, +-1.36136069169392123768e-02, +-1.29803359903072849241e-02, +-1.23420748949298001579e-02, +-1.16991619788734471652e-02, +-1.10519370840110493781e-02, +-1.04007413695592701441e-02, +-9.74591713539885336204e-03, +-9.08780764526554395155e-03, +-8.42675694990374125892e-03, +-7.76310971027038485004e-03, +-7.09721102088000169172e-03, +-6.42940623337920000302e-03, +-5.76004078043931225933e-03, +-5.08946000005612835676e-03, +-4.41800896034429992076e-03, +-3.74603228491338785533e-03, +-3.07387397891339432532e-03, +-2.40187725583507205585e-03, +-1.73038436515272897598e-03, +-1.05973642089167863906e-03, +-3.90273231208217510901e-04, + 2.77666870936983212030e-04, + 9.43747195927376416637e-04, + 1.60763286437934816049e-03, + 2.26899097268967123858e-03, + 2.92749075716241266912e-03, + 3.58280375663248612170e-03, + 4.23460397351204959754e-03, + 4.88256803317746110316e-03, + 5.52637534162357668688e-03, + 6.16570824130805751617e-03, + 6.80025216511182754170e-03, + 7.42969578834302112058e-03, + 8.05373117871052007777e-03, + 8.67205394419879975476e-03, + 9.28436337877218062498e-03, + 9.89036260584076794278e-03, + 1.04897587194219873291e-02, + 1.10822629229305347903e-02, + 1.16675906655330941658e-02, + 1.22454617760050857300e-02, + 1.28156005940266576326e-02, + 1.33777360988594062191e-02, + 1.39316020353439252305e-02, + 1.44769370371622355803e-02, + 1.50134847473070466572e-02, + 1.55409939357074259464e-02, + 1.60592186139547725421e-02, + 1.65679181470810912846e-02, + 1.70668573623377166359e-02, + 1.75558066549289203129e-02, + 1.80345420906532633021e-02, + 1.85028455054086320153e-02, + 1.89605046015185567387e-02, + 1.94073130408384669776e-02, + 1.98430705346031681369e-02, + 2.02675829299774241943e-02, + 2.06806622932754168021e-02, + 2.10821269898129222409e-02, + 2.14718017603625459244e-02, + 2.18495177941796202281e-02, + 2.22151127985720682478e-02, + 2.25684310649855168762e-02, + 2.29093235315810418717e-02, + 2.32376478422810298086e-02, + 2.35532684022618996056e-02, + 2.38560564298757396551e-02, + 2.41458900049817716538e-02, + 2.44226541136732810955e-02, + 2.46862406893853837675e-02, + 2.49365486503724774481e-02, + 2.51734839335446165809e-02, + 2.53969595246556420487e-02, + 2.56068954848354853049e-02, + 2.58032189734641453915e-02, + 2.59858642673822630431e-02, + 2.61547727764399259853e-02, + 2.63098930553838268598e-02, + 2.64511808120856638238e-02, + 2.65785989121172516736e-02, + 2.66921173796784670651e-02, + 2.67917133948867500215e-02, + 2.68773712874392570193e-02, + 2.69490825266583827746e-02, + 2.70068457079358954787e-02, + 2.70506665355911626869e-02, + 2.70805578021602322281e-02, + 2.70965393641366091015e-02, + 2.70986381141830531827e-02, + 2.70868879498386908034e-02, + 2.70613297387449595888e-02, + 2.70220112804171637422e-02, + 2.69689872645891524916e-02, + 2.69023192261612989484e-02, + 2.68220754967820745884e-02, + 2.67283311530973760606e-02, + 2.66211679617003732501e-02, + 2.65006743208199592454e-02, + 2.63669451987833119988e-02, + 2.62200820692939373657e-02, + 2.60601928435633990733e-02, + 2.58873917993413214800e-02, + 2.57017995068857182939e-02, + 2.55035427519193710899e-02, + 2.52927544556184984159e-02, + 2.50695735916821975386e-02, + 2.48341451005307974065e-02, + 2.45866198006852616775e-02, + 2.43271542973778100161e-02, + 2.40559108884488212499e-02, + 2.37730574675824729569e-02, + 2.34787674249385819314e-02, + 2.31732195452361150467e-02, + 2.28565979033475072391e-02, + 2.25290917574611608554e-02, + 2.21908954398750551951e-02, + 2.18422082454798119344e-02, + 2.14832343179954671220e-02, + 2.11141825340238932507e-02, + 2.07352663849828984521e-02, + 2.03467038569848726604e-02, + 1.99487173087274823058e-02, + 1.95415333474632871291e-02, + 1.91253827031149341298e-02, + 1.87005001006056471857e-02, + 1.82671241304729649324e-02, + 1.78254971178373536334e-02, + 1.73758649897937239581e-02, + 1.69184771412996537432e-02, + 1.64535862996303787475e-02, + 1.59814483874737844893e-02, + 1.55023223847373312068e-02, + 1.50164701891417791402e-02, + 1.45241564756737676078e-02, + 1.40256485549719173145e-02, + 1.35212162307227472952e-02, + 1.30111316561379447565e-02, + 1.24956691895912394563e-02, + 1.19751052494878589688e-02, + 1.14497181684445926975e-02, + 1.09197880468538122134e-02, + 1.03855966059087159725e-02, + 9.84742704016562143965e-03, + 9.30556386971926295659e-03, + 8.76029279206604755137e-03, + 8.21190053373426452621e-03, + 7.66067470175298657897e-03, + 7.10690363503945106427e-03, + 6.55087625577790554771e-03, + 5.99288192086684483317e-03, + 5.43321027350959859931e-03, + 4.87215109502278989617e-03, + 4.30999415693893248719e-03, + 3.74702907347534584434e-03, + 3.18354515444554302464e-03, + 2.61983125868587608809e-03, + 2.05617564807023672779e-03, + 1.49286584218635853295e-03, + 9.30188473745678081825e-04, + 3.68429144797911432754e-04, +-1.92127716177123029819e-04, +-7.51198996231790326432e-04, +-1.30850303889562991251e-03, +-1.86375978403549190029e-03, +-2.41669090655965632108e-03, +-2.96701995390177180115e-03, +-3.51447248221491799144e-03, +-4.05877619121137057229e-03, +-4.59966105758124674252e-03, +-5.13685946692752325171e-03, +-5.67010634415242211620e-03, +-6.19913928223347811958e-03, +-6.72369866932763082107e-03, +-7.24352781414225668777e-03, +-7.75837306951438713393e-03, +-8.26798395413882135363e-03, +-8.77211327238880053669e-03, +-9.27051723217174085401e-03, +-9.76295556076584719607e-03, +-1.02491916185828580571e-02, +-1.07289925108050229752e-02, +-1.12021291968433227976e-02, +-1.16683765975679858140e-02, +-1.21275137002619763649e-02, +-1.25793236612475982372e-02, +-1.30235939061431136438e-02, +-1.34601162277011333901e-02, +-1.38886868811863382206e-02, +-1.43091066772499612286e-02, +-1.47211810722588463257e-02, +-1.51247202560407922184e-02, +-1.55195392370066180543e-02, +-1.59054579246123636849e-02, +-1.62823012091269786472e-02, +-1.66498990386690776111e-02, +-1.70080864934834194435e-02, +-1.73567038574233001302e-02, +-1.76955966866107171354e-02, +-1.80246158752456059338e-02, +-1.83436177185377254084e-02, +-1.86524639727363474029e-02, +-1.89510219122339153286e-02, +-1.92391643837212557300e-02, +-1.95167698573757708580e-02, +-1.97837224750605396306e-02, +-2.00399120955206018480e-02, +-2.02852343365580237156e-02, +-2.05195906141726648608e-02, +-2.07428881786561915279e-02, +-2.09550401476275363621e-02, +-2.11559655360012838221e-02, +-2.13455892828807378137e-02, +-2.15238422753686667321e-02, +-2.16906613692930197446e-02, +-2.18459894068418723767e-02, +-2.19897752311081634558e-02, +-2.21219736975437064608e-02, +-2.22425456823232385595e-02, +-2.23514580876230314899e-02, +-2.24486838438175441424e-02, +-2.25342019086016941143e-02, +-2.26079972630452222249e-02, +-2.26700609045897422122e-02, +-2.27203898369985682337e-02, +-2.27589870572722542674e-02, +-2.27858615395436989171e-02, +-2.28010282159679666947e-02, +-2.28045079546240481161e-02, +-2.27963275344472623973e-02, +-2.27765196172116414497e-02, +-2.27451227165837051303e-02, +-2.27021811642711575374e-02, +-2.26477450732895796426e-02, +-2.25818702983737081003e-02, +-2.25046183935598033410e-02, +-2.24160565669674592681e-02, +-2.23162576328110422164e-02, +-2.22052999606712764269e-02, +-2.20832674220598039472e-02, +-2.19502493343100429923e-02, +-2.18063404018299551723e-02, +-2.16516406547519850434e-02, +-2.14862553850184781479e-02, +-2.13102950799411924865e-02, +-2.11238753532740700103e-02, +-2.09271168738412970123e-02, +-2.07201452917621688210e-02, +-2.05030911623162483137e-02, +-2.02760898674933312535e-02, +-2.00392815352738624946e-02, +-1.97928109566855824075e-02, +-1.95368275006852568088e-02, +-1.92714850269127511984e-02, +-1.89969417963674683247e-02, +-1.87133603800582019872e-02, +-1.84209075656767175266e-02, +-1.81197542623479680712e-02, +-1.78100754035098000905e-02, +-1.74920498479764381650e-02, +-1.71658602792400527548e-02, +-1.68316931030659776292e-02, +-1.64897383434381879230e-02, +-1.61401895369109177336e-02, +-1.57832436254263346054e-02, +-1.54191008476533275573e-02, +-1.50479646289087866384e-02, +-1.46700414697199573583e-02, +-1.42855408330877838713e-02, +-1.38946750305117498053e-02, +-1.34976591068377456406e-02, +-1.30947107239892130554e-02, +-1.26860500436455827383e-02, +-1.22718996089274719891e-02, +-1.18524842251538416876e-02, +-1.14280308397327317466e-02, +-1.09987684212486756113e-02, +-1.05649278378112127658e-02, +-1.01267417347274506223e-02, +-9.68444441156269923698e-03, +-9.23827169865409740523e-03, +-8.78846083313997161746e-03, +-8.33525033457069991494e-03, +-7.87887988016375100109e-03, +-7.41959017977004194749e-03, +-6.95762285061261864794e-03, +-6.49322029186454475341e-03, +-6.02662555912889408988e-03, +-5.55808223888622741915e-03, +-5.08783432297227420499e-03, +-4.61612608315053844776e-03, +-4.14320194584339666216e-03, +-3.66930636708468534829e-03, +-3.19468370775774284862e-03, +-2.71957810918098006822e-03, +-2.24423336910424412252e-03, +-1.76889281817741881794e-03, +-1.29379919695378617014e-03, +-8.19194533489142270866e-04, +-3.45320021597831196877e-04, + 1.27584100174339069422e-04, + 5.99278668799195350127e-04, + 1.06952571617924155171e-03, + 1.53808858766556200148e-03, + 2.00473205962055367468e-03, + 2.46922245597071959855e-03, + 2.93132776369034713654e-03, + 3.39081774716058033034e-03, + 3.84746406134854872921e-03, + 4.30104036375060765768e-03, + 4.75132242504706578390e-03, + 5.19808823841395525878e-03, + 5.64111812743960539668e-03, + 6.08019485259521982184e-03, + 6.51510371620631252576e-03, + 6.94563266587837867261e-03, + 7.37157239632470640683e-03, + 7.79271644955021464130e-03, + 8.20886131334327799614e-03, + 8.61980651802961989061e-03, + 9.02535473144288127867e-03, + 9.42531185206835209200e-03, + 9.81948710031542437715e-03, + 1.02076931078787062901e-02, + 1.05897460051441894696e-02, + 1.09654655066032842570e-02, + 1.13346749942337312461e-02, + 1.16972015988115480428e-02, + 1.20528762791150233225e-02, + 1.24015338989890838706e-02, + 1.27430133022312791491e-02, + 1.30771573852710050467e-02, + 1.34038131676064240644e-02, + 1.37228318599705717551e-02, + 1.40340689301969769737e-02, + 1.43373841667557219703e-02, + 1.46326417399349796578e-02, + 1.49197102606399897157e-02, + 1.51984628367875466287e-02, + 1.54687771272712503573e-02, + 1.57305353934761547874e-02, + 1.59836245483238222065e-02, + 1.62279362028255533246e-02, + 1.64633667101300000535e-02, + 1.66898172070444779369e-02, + 1.69071936530182861946e-02, + 1.71154068665722303155e-02, + 1.73143725591620549487e-02, + 1.75040113664655661019e-02, + 1.76842488770822502120e-02, + 1.78550156586383436397e-02, + 1.80162472812886650941e-02, + 1.81678843386109678537e-02, + 1.83098724658869831117e-02, + 1.84421623557678958372e-02, + 1.85647097713225045501e-02, + 1.86774755564665419227e-02, + 1.87804256437758242126e-02, + 1.88735310596836944330e-02, + 1.89567679270675991388e-02, + 1.90301174652290280842e-02, + 1.90935659872729333875e-02, + 1.91471048948949201796e-02, + 1.91907306705839213190e-02, + 1.92244448672513647269e-02, + 1.92482540952976406701e-02, + 1.92621700071291257483e-02, + 1.92662092791390723856e-02, + 1.92603935911679381709e-02, + 1.92447496034597632930e-02, + 1.92193089311317975854e-02, + 1.91841081161766568997e-02, + 1.91391885970173640519e-02, + 1.90845966756356746896e-02, + 1.90203834822977521646e-02, + 1.89466049378990836205e-02, + 1.88633217139549183572e-02, + 1.87705991902617184974e-02, + 1.86685074102564685372e-02, + 1.85571210341025014112e-02, + 1.84365192895308768750e-02, + 1.83067859204682249763e-02, + 1.81680091334814851345e-02, + 1.80202815420731528306e-02, + 1.78637001088602434540e-02, + 1.76983660856705124487e-02, + 1.75243849515933046435e-02, + 1.73418663490196370280e-02, + 1.71509240177099529789e-02, + 1.69516757269280171627e-02, + 1.67442432056789658468e-02, + 1.65287520710933055756e-02, + 1.63053317549959643495e-02, + 1.60741154287042248283e-02, + 1.58352399260948337179e-02, + 1.55888456649855098451e-02, + 1.53350765668743439091e-02, + 1.50740799750810755553e-02, + 1.48060065713376716456e-02, + 1.45310102908721653497e-02, + 1.42492482360351419013e-02, + 1.39608805885138576031e-02, + 1.36660705201842418155e-02, + 1.33649841026482960049e-02, + 1.30577902155067059053e-02, + 1.27446604534163440703e-02, + 1.24257690319823609071e-02, + 1.21012926925372719250e-02, + 1.17714106058561026463e-02, + 1.14363042748611334204e-02, + 1.10961574363676110377e-02, + 1.07511559619219848605e-02, + 1.04014877577871447251e-02, + 1.00473426641261246589e-02, + 9.68891235343915212253e-03, + 9.32639022830554151322e-03, + 8.95997131848667513476e-03, + 8.58985217744295814768e-03, + 8.21623077831776238433e-03, + 7.83930640944576623275e-03, + 7.45927956943647635368e-03, + 7.07635186189118064320e-03, + 6.69072588980388575225e-03, + 6.30260514970595094736e-03, + 5.91219392560345287368e-03, + 5.51969718276637197341e-03, + 5.12532046142244023662e-03, + 4.72926977040892190796e-03, + 4.33175148083997027526e-03, + 3.93297221983980160170e-03, + 3.53313876439927251547e-03, + 3.13245793540825817960e-03, + 2.73113649191582047102e-03, + 2.32938102567640907548e-03, + 1.92739785602901348045e-03, + 1.52539292516795199454e-03, + 1.12357169385324685146e-03, + 7.22139037616026076630e-04, + 3.21299143509566089132e-04, +-7.87445925439102364842e-05, +-4.77789667756481134173e-04, +-8.75634573781077039240e-04, +-1.27207889726797546831e-03, +-1.66692341962379432171e-03, +-2.05997021592245954311e-03, +-2.45102275292159678052e-03, +-2.83988598613405971924e-03, +-3.22636645590845556192e-03, +-3.61027238247302534671e-03, +-3.99141375989387706819e-03, +-4.36960244890573310667e-03, +-4.74465226856734742511e-03, +-5.11637908669945132983e-03, +-5.48460090906132020916e-03, +-5.84913796722293360258e-03, +-6.20981280509260748224e-03, +-6.56645036405622325310e-03, +-6.91887806669126605857e-03, +-7.26692589901343100750e-03, +-7.61042649121839841903e-03, +-7.94921519688219710420e-03, +-8.28313017058056322295e-03, +-8.61201244389523008771e-03, +-8.93570599976736823500e-03, +-9.25405784516927093497e-03, +-9.56691808205707705515e-03, +-9.87413997657404438058e-03, +-1.01755800264738422573e-02, +-1.04710980267316584175e-02, +-1.07605571333162300385e-02, +-1.10438239250919990192e-02, +-1.13207684638271209587e-02, +-1.15912643522783440769e-02, +-1.18551887903295075782e-02, +-1.21124226291589674048e-02, +-1.23628504234125462247e-02, +-1.26063604813613176076e-02, +-1.28428449130213884893e-02, +-1.30721996762182875867e-02, +-1.32943246205750771616e-02, +-1.35091235294078314266e-02, +-1.37165041595128135710e-02, +-1.39163782788270101731e-02, +-1.41086617019519286464e-02, +-1.42932743235239592683e-02, +-1.44701401494216879556e-02, +-1.46391873257979802936e-02, +-1.48003481659278162547e-02, +-1.49535591748633858722e-02, +-1.50987610718883325661e-02, +-1.52358988107658115813e-02, +-1.53649215977745036421e-02, +-1.54857829075290397841e-02, +-1.55984404965814546506e-02, +-1.57028564148030853886e-02, +-1.57989970145448431482e-02, +-1.58868329575775346640e-02, +-1.59663392198137396583e-02, +-1.60374950938135772682e-02, +-1.61002841890790400481e-02, +-1.61546944301414231726e-02, +-1.62007180524483263007e-02, +-1.62383515960572676062e-02, +-1.62675958971449409474e-02, +-1.62884560773407099932e-02, +-1.63009415308956705226e-02, +-1.63050659096987474173e-02, +-1.63008471061523926848e-02, +-1.62883072339218455682e-02, +-1.62674726065730329561e-02, +-1.62383737141145109706e-02, +-1.62010451974609233361e-02, +-1.61555258208356707084e-02, +-1.61018584421316855726e-02, +-1.60400899812505326469e-02, +-1.59702713864408145372e-02, +-1.58924575986573272945e-02, +-1.58067075139647107707e-02, +-1.57130839440085059988e-02, +-1.56116535745792449352e-02, +-1.55024869222944727820e-02, +-1.53856582894260490724e-02, +-1.52612457168996174667e-02, +-1.51293309354949591372e-02, +-1.49899993152762481957e-02, +-1.48433398132821487564e-02, +-1.46894449195070758013e-02, +-1.45284106012046419082e-02, +-1.43603362455460986657e-02, +-1.41853246006673119201e-02, +-1.40034817151370259009e-02, +-1.38149168758828280734e-02, +-1.36197425446084856987e-02, +-1.34180742927401692316e-02, +-1.32100307349369578552e-02, +-1.29957334612042334221e-02, +-1.27753069676474068084e-02, +-1.25488785859041301896e-02, +-1.23165784112953900081e-02, +-1.20785392297338319001e-02, +-1.18348964434312736022e-02, +-1.15857879954438421077e-02, +-1.13313542930994892027e-02, +-1.10717381303457890890e-02, +-1.08070846090634192782e-02, +-1.05375410593865573988e-02, +-1.02632569590727744380e-02, +-9.98438385196800254340e-03, +-9.70107526560752726763e-03, +-9.41348662799971515336e-03, +-9.12177518363594015682e-03, +-8.82609990877025046840e-03, +-8.52662142601712247370e-03, +-8.22350191830830204442e-03, +-7.91690504225831676033e-03, +-7.60699584098104789748e-03, +-7.29394065640553979080e-03, +-6.97790704113636535422e-03, +-6.65906366990342071799e-03, +-6.33758025065010895116e-03, +-6.01362743530314651508e-03, +-5.68737673027295675271e-03, +-5.35900040672940281006e-03, +-5.02867141070039921913e-03, +-4.69656327303835750137e-03, +-4.36285001930248206997e-03, +-4.02770607960259777180e-03, +-3.69130619844926536818e-03, +-3.35382534465939949331e-03, +-3.01543862135967731183e-03, +-2.67632117613655082580e-03, +-2.33664811137678819775e-03, +-1.99659439484433081508e-03, +-1.65633477053923894307e-03, +-1.31604366988200688349e-03, +-9.75895123270567642695e-04, +-6.36062672051197525343e-04, +-2.96719280950014205507e-04, + 4.19627489923029214371e-05, + 3.79811866940293777015e-04, + 7.16657358192283769176e-04, + 1.05232942947910620979e-03, + 1.38665929358586822832e-03, + 1.71947925326047606175e-03, + 2.05062278436349190031e-03, + 2.37992461822022008389e-03, + 2.70722082313579063065e-03, + 3.03234888503091078518e-03, + 3.35514778716229861502e-03, + 3.67545808888595972735e-03, + 3.99312200342836869094e-03, + 4.30798347462560838467e-03, + 4.61988825259515914490e-03, + 4.92868396830371639783e-03, + 5.23422020699498662111e-03, + 5.53634858044424124635e-03, + 5.83492279800282634405e-03, + 6.12979873640210736613e-03, + 6.42083450828168002950e-03, + 6.70789052941064140034e-03, + 6.99082958457222531506e-03, + 7.26951689207744420479e-03, + 7.54382016688265842619e-03, + 7.81360968227803008579e-03, + 8.07875833012169572434e-03, + 8.33914167959036965738e-03, + 8.59463803442023742407e-03, + 8.84512848861381158205e-03, + 9.09049698058539933088e-03, + 9.33063034572383098730e-03, + 9.56541836734724204572e-03, + 9.79475382602876601390e-03, + 1.00185325472712388750e-02, + 1.02366534475112885144e-02, + 1.04490185784319629392e-02, + 1.06555331695659429025e-02, + 1.08561056691723126222e-02, + 1.10506477833681605177e-02, + 1.12390745135014444300e-02, + 1.14213041917481192972e-02, + 1.15972585149209383992e-02, + 1.17668625764762845715e-02, + 1.19300448967066957673e-02, + 1.20867374511089888806e-02, + 1.22368756969161197878e-02, + 1.23803985977854972417e-02, + 1.25172486466337395256e-02, + 1.26473718866117884607e-02, + 1.27707179302137523863e-02, + 1.28872399765134221933e-02, + 1.29968948265256969976e-02, + 1.30996428966874464001e-02, + 1.31954482304573617740e-02, + 1.32842785080317399987e-02, + 1.33661050541768675060e-02, + 1.34409028441777739227e-02, + 1.35086505079049911532e-02, + 1.35693303320018558017e-02, + 1.36229282601955156012e-02, + 1.36694338917359037994e-02, + 1.37088404779683696588e-02, + 1.37411449170452750618e-02, + 1.37663477467847624597e-02, + 1.37844531356839973546e-02, + 1.37954688720959822018e-02, + 1.37994063515802581343e-02, + 1.37962805624378334612e-02, + 1.37861100694423310831e-02, + 1.37689169957797372806e-02, + 1.37447270032107649734e-02, + 1.37135692704694871907e-02, + 1.36754764699141325573e-02, + 1.36304847424457160204e-02, + 1.35786336707117930717e-02, + 1.35199662506130090928e-02, + 1.34545288611307815863e-02, + 1.33823712324960784892e-02, + 1.33035464127193650552e-02, + 1.32181107325021699600e-02, + 1.31261237685532539815e-02, + 1.30276483053305639631e-02, + 1.29227502952338896280e-02, + 1.28114988172704970942e-02, + 1.26939660342200184157e-02, + 1.25702271483237072724e-02, + 1.24403603555233947114e-02, + 1.23044467982784695020e-02, + 1.21625705169872422307e-02, + 1.20148184000413785211e-02, + 1.18612801325425308574e-02, + 1.17020481437095178606e-02, + 1.15372175530077808459e-02, + 1.13668861150298707019e-02, + 1.11911541631600167795e-02, + 1.10101245520525005406e-02, + 1.08239025989581676146e-02, + 1.06325960239305756377e-02, + 1.04363148889449076223e-02, + 1.02351715359647547215e-02, + 1.00292805239893083324e-02, + 9.81875856511689806827e-03, + 9.60372445965929077971e-03, + 9.38429903034274093265e-03, + 9.16060505563077998037e-03, + 8.93276720220602567235e-03, + 8.70091195664717161062e-03, + 8.46516755633743532561e-03, + 8.22566391964303297857e-03, + 7.98253257539762242634e-03, + 7.73590659173173638558e-03, + 7.48592050428459592631e-03, + 7.23271024383650030370e-03, + 6.97641306340083741655e-03, + 6.71716746481300884530e-03, + 6.45511312485713174836e-03, + 6.19039082096706390346e-03, + 5.92314235654277116555e-03, + 5.65351048592053172237e-03, + 5.38163883903518876911e-03, + 5.10767184581618297751e-03, + 4.83175466035329001513e-03, + 4.55403308487579983055e-03, + 4.27465349357983477596e-03, + 3.99376275634679561710e-03, + 3.71150816239089074641e-03, + 3.42803734387406560530e-03, + 3.14349819952992014238e-03, + 2.85803881833283880340e-03, + 2.57180740325433027441e-03, + 2.28495219514192630592e-03, + 1.99762139676367333693e-03, + 1.70996309705198873234e-03, + 1.42212519558894585903e-03, + 1.13425532736955879051e-03, + 8.46500787880119249379e-04, + 5.59008458531536360676e-04, + 2.71924732482213711831e-04, +-1.46045591101362367902e-05, +-3.00434220371862336588e-04, +-5.85419763496916080447e-04, +-8.69417480990889736912e-04, +-1.15228451734444565895e-03, +-1.43387894009652252202e-03, +-1.71405981025574941264e-03, +-1.99268725204318009406e-03, +-2.26962252192313383714e-03, +-2.54472807688939806764e-03, +-2.81786764197139655633e-03, +-3.08890627693018818625e-03, +-3.35771044210986593925e-03, +-3.62414806341412312415e-03, +-3.88808859637569193338e-03, +-4.14940308928948755479e-03, +-4.40796424537761438733e-03, +-4.66364648395760274940e-03, +-4.91632600058568031837e-03, +-5.16588082614466512915e-03, +-5.41219088485122776233e-03, +-5.65513805115323408418e-03, +-5.89460620549208617197e-03, +-6.13048128890366673949e-03, +-6.36265135643233371854e-03, +-6.59100662933489230694e-03, +-6.81543954604840913902e-03, +-7.03584481190112302068e-03, +-7.25211944754226237736e-03, +-7.46416283606952078722e-03, +-7.67187676883409296058e-03, +-7.87516548990104849060e-03, +-8.07393573914804915659e-03, +-8.26809679398036317943e-03, +-8.45756050964779383661e-03, +-8.64224135814309693537e-03, +-8.82205646566693382771e-03, +-8.99692564864382551826e-03, +-9.16677144827266789096e-03, +-9.33151916359954529401e-03, +-9.49109688309758385560e-03, +-9.64543551474287760850e-03, +-9.79446881457346311961e-03, +-9.93813341372091867132e-03, +-1.00763688439045248635e-02, +-1.02091175613780275888e-02, +-1.03363249693213758024e-02, +-1.04579394386685748525e-02, +-1.05739123273658041507e-02, +-1.06841979980529435540e-02, +-1.07887538341634794947e-02, +-1.08875402544387003823e-02, +-1.09805207258518982422e-02, +-1.10676617749403266577e-02, +-1.11489329975425002783e-02, +-1.12243070669403085388e-02, +-1.12937597404047310179e-02, +-1.13572698641464103764e-02, +-1.14148193766721185033e-02, +-1.14663933105489043718e-02, +-1.15119797925795526450e-02, +-1.15515700423923072665e-02, +-1.15851583694501700239e-02, +-1.16127421684842080385e-02, +-1.16343219133579756086e-02, +-1.16499011493693144931e-02, +-1.16594864839973874626e-02, +-1.16630875761035632254e-02, +-1.16607171235953484961e-02, +-1.16523908495632707444e-02, +-1.16381274869015692575e-02, +-1.16179487614245235960e-02, +-1.15918793734899987224e-02, +-1.15599469781440481603e-02, +-1.15221821637996792859e-02, +-1.14786184294645918214e-02, +-1.14292921605328150897e-02, +-1.13742426031563578781e-02, +-1.13135118372134652748e-02, +-1.12471447478901080685e-02, +-1.11751889958936409530e-02, +-1.10976949863161849369e-02, +-1.10147158361676694022e-02, +-1.09263073405979870001e-02, +-1.08325279378290572491e-02, +-1.07334386728172945930e-02, +-1.06291031596689976302e-02, +-1.05195875428303799864e-02, +-1.04049604570749746474e-02, +-1.02852929863124966520e-02, +-1.01606586212423712773e-02, +-1.00311332158768314049e-02, +-9.89679494295862653697e-03, +-9.75772424829860450524e-03, +-9.61400380405963254915e-03, +-9.46571846101251432315e-03, +-9.31295519979207127303e-03, +-9.15580308117954107250e-03, +-8.99435319544003054892e-03, +-8.82869861074311521043e-03, +-8.65893432069447625821e-03, +-8.48515719100898131722e-03, +-8.30746590535331487504e-03, +-8.12596091038898099557e-03, +-7.94074436004471931327e-03, +-7.75192005904976402797e-03, +-7.55959340575841978738e-03, +-7.36387133429604930773e-03, +-7.16486225605968488073e-03, +-6.96267600060247564275e-03, +-6.75742375593618195551e-03, +-6.54921800828115602267e-03, +-6.33817248129906873205e-03, +-6.12440207483747056649e-03, +-5.90802280322155672770e-03, +-5.68915173312445864029e-03, +-5.46790692104878739421e-03, +-5.24440735045367430189e-03, +-5.01877286855873742250e-03, +-4.79112412285956183744e-03, +-4.56158249738753112518e-03, +-4.33027004874617267582e-03, +-4.09730944195998200014e-03, +-3.86282388616571940171e-03, +-3.62693707018273397286e-03, +-3.38977309799298612628e-03, +-3.15145642416600349836e-03, +-2.91211178926129628936e-03, +-2.67186415524058896998e-03, +-2.43083864092491410552e-03, +-2.18916045752724818321e-03, +-1.94695484429555434880e-03, +-1.70434700429766003774e-03, +-1.46146204038146722802e-03, +-1.21842489134170429109e-03, +-9.75360268326885652967e-04, +-7.32392591517812274748e-04, +-4.89645927108687487733e-04, +-2.47243924624317883750e-04, +-5.30975460243512911756e-06, + 2.36033953325794955153e-04, + 4.76665171927515821017e-04, + 7.16462537401301477295e-04, + 9.55305409921098193718e-04, + 1.19307393366231218393e-03, + 1.42964909627860559810e-03, + 1.66491278780242935725e-03, + 1.89874785893865663695e-03, + 2.13103817872366176761e-03, + 2.36166869152246855501e-03, + 2.59052547333455795292e-03, + 2.81749578738373649203e-03, + 3.04246813896196085722e-03, + 3.26533232950441303435e-03, + 3.48597950986718595895e-03, + 3.70430223278326144556e-03, + 3.92019450447253243325e-03, + 4.13355183537975935659e-03, + 4.34427129001856843216e-03, + 4.55225153589615232075e-03, + 4.75739289149763357190e-03, + 4.95959737330627960239e-03, + 5.15876874183868530666e-03, + 5.35481254667346043274e-03, + 5.54763617045254779636e-03, + 5.73714887183583450297e-03, + 5.92326182738835572278e-03, + 6.10588817238264490450e-03, + 6.28494304049680499458e-03, + 6.46034360239086408867e-03, + 6.63200910314530080181e-03, + 6.79986089854376415248e-03, + 6.96382249018552904052e-03, + 7.12381955941148153205e-03, + 7.27978000003043010380e-03, + 7.43163394983032809388e-03, + 7.57931382086227036637e-03, + 7.72275432848473775138e-03, + 7.86189251915526618464e-03, + 7.99666779695973849174e-03, + 8.12702194886731447976e-03, + 8.25289916870263103033e-03, + 8.37424607982448221399e-03, + 8.49101175650416456486e-03, + 8.60314774399449817832e-03, + 8.71060807728277902706e-03, + 8.81334929852170718967e-03, + 8.91133047313173894122e-03, + 9.00451320457064906255e-03, + 9.09286164776551726618e-03, + 9.17634252120343510417e-03, + 9.25492511767886209817e-03, + 9.32858131369380602638e-03, + 9.39728557751129400799e-03, + 9.46101497585938137902e-03, + 9.51974917928707746462e-03, + 9.57347046617182048656e-03, + 9.62216372537993622216e-03, + 9.66581645758253331369e-03, + 9.70441877522852311411e-03, + 9.73796340117899505984e-03, + 9.76644566600631813813e-03, + 9.78986350396279965402e-03, + 9.80821744762437608411e-03, + 9.82151062121512652414e-03, + 9.82974873261935853941e-03, + 9.83294006408857654278e-03, + 9.83109546165142171581e-03, + 9.82422832323481126648e-03, + 9.81235458550605912920e-03, + 9.79549270944552429030e-03, + 9.77366366466025406068e-03, + 9.74689091245018769671e-03, + 9.71520038763806249860e-03, + 9.67862047917591658552e-03, + 9.63718200954081366527e-03, + 9.59091821293355135947e-03, + 9.53986471229417709594e-03, + 9.48405949514947999024e-03, + 9.42354288830722815196e-03, + 9.35835753141333638594e-03, + 9.28854834938808680833e-03, + 9.21416252375845123979e-03, + 9.13524946290390424397e-03, + 9.05186077123359793262e-03, + 8.96405021731353467140e-03, + 8.87187370096227494176e-03, + 8.77538921933519559804e-03, + 8.67465683201655221590e-03, + 8.56973862514041548333e-03, + 8.46069867456020023588e-03, + 8.34760300808964732233e-03, + 8.23051956683512782320e-03, + 8.10951816564266063370e-03, + 7.98467045268167613381e-03, + 7.85604986818807735083e-03, + 7.72373160239066269828e-03, + 7.58779255264339144021e-03, + 7.44831127978854735938e-03, + 7.30536796377457674917e-03, + 7.15904435855267175237e-03, + 7.00942374627864812214e-03, + 6.85659089084312764473e-03, + 6.70063199075772355368e-03, + 6.54163463142106230142e-03, + 6.37968773679228450674e-03, + 6.21488152049734249999e-03, + 6.04730743639451170240e-03, + 5.87705812862679335268e-03, + 5.70422738118673677138e-03, + 5.52891006702203955531e-03, + 5.35120209670836722432e-03, + 5.17120036671731789918e-03, + 4.98900270730638639716e-03, + 4.80470783005945180355e-03, + 4.61841527510534633622e-03, + 4.43022535804147177957e-03, + 4.24023911659228945614e-03, + 4.04855825702851463560e-03, + 3.85528510037712974709e-03, + 3.66052252844891639130e-03, + 3.46437392971235937414e-03, + 3.26694314504209770700e-03, + 3.06833441336932816884e-03, + 2.86865231726372458751e-03, + 2.66800172847322068781e-03, + 2.46648775345124351629e-03, + 2.26421567889880867575e-03, + 2.06129091734864790947e-03, + 1.85781895282100093132e-03, + 1.65390528657631021014e-03, + 1.44965538299551312262e-03, + 1.24517461561208316219e-03, + 1.04056821332572727035e-03, + 8.35941206823879187984e-04, + 6.31398375237409098873e-04, + 4.27044193058938911355e-04, + 2.22982777348387794809e-04, + 1.93178352541883997372e-05, +-1.83847388125652280721e-04, +-3.86410161515063485180e-04, +-5.88268318839344113436e-04, +-7.89320310186791547317e-04, +-9.89465252327087745748e-04, +-1.18860297876262669368e-03, +-1.38663408928657127910e-03, +-1.58345999902536368857e-03, +-1.77898298694016492559e-03, +-1.97310624376432260790e-03, +-2.16573391935423681734e-03, +-2.35677116942951958567e-03, +-2.54612420168103805937e-03, +-2.73370032122395708804e-03, +-2.91940797537506343401e-03, +-3.10315679773186291548e-03, +-3.28485765153320842871e-03, +-3.46442267228143797181e-03, +-3.64176530960461748362e-03, +-3.81680036834099439130e-03, +-3.98944404882473329516e-03, +-4.15961398635617159159e-03, +-4.32722928983605027026e-03, +-4.49221057954843436960e-03, +-4.65448002407309498196e-03, +-4.81396137631140419444e-03, +-4.97058000860978871360e-03, +-5.12426294696375662918e-03, +-5.27493890428890055411e-03, +-5.42253831274242328875e-03, +-5.56699335508204027484e-03, +-5.70823799504863171883e-03, +-5.84620800675817245406e-03, +-5.98084100309233864662e-03, +-6.11207646307366722627e-03, +-6.23985575821544256880e-03, +-6.36412217783412659938e-03, +-6.48482095331432296242e-03, +-6.60189928131710984660e-03, +-6.71530634592089337165e-03, +-6.82499333968801785016e-03, +-6.93091348364723199016e-03, +-7.03302204618568189975e-03, +-7.13127636084264718980e-03, +-7.22563584299942916062e-03, +-7.31606200545875488828e-03, +-7.40251847290886687281e-03, +-7.48497099526800394043e-03, +-7.56338745990427392674e-03, +-7.63773790272863697948e-03, +-7.70799451815705905650e-03, +-7.77413166794023880596e-03, +-7.83612588885893024404e-03, +-7.89395589928373019040e-03, +-7.94760260459900953756e-03, +-7.99704910149071600267e-03, +-8.04228068109907878735e-03, +-8.08328483103710852820e-03, +-8.12005123627678772336e-03, +-8.15257177890556759825e-03, +-8.18084053675576655662e-03, +-8.20485378091061375028e-03, +-8.22460997209095365235e-03, +-8.24010975592739773610e-03, +-8.25135595712299906024e-03, +-8.25835357251225588016e-03, +-8.26110976302289051754e-03, +-8.25963384454711686822e-03, +-8.25393727773001892323e-03, +-8.24403365668276502665e-03, +-8.22993869662941301968e-03, +-8.21167022049609611478e-03, +-8.18924814445231435966e-03, +-8.16269446241428900390e-03, +-8.13203322952094770359e-03, +-8.09729054459370524433e-03, +-8.05849453159142650738e-03, +-8.01567532007289515472e-03, +-7.96886502467894497492e-03, +-7.91809772364769626218e-03, +-7.86340943637591806292e-03, +-7.80483810004095092394e-03, +-7.74242354529683460967e-03, +-7.67620747106049876318e-03, +-7.60623341840202440295e-03, +-7.53254674355573021483e-03, +-7.45519459006761028158e-03, +-7.37422586009548602926e-03, +-7.28969118487934625988e-03, +-7.20164289439836468459e-03, +-7.11013498623295006618e-03, +-7.01522309364934187198e-03, +-6.91696445292533119292e-03, +-6.81541786993564071423e-03, +-6.71064368601629723105e-03, +-6.60270374312706912617e-03, +-6.49166134833155817480e-03, +-6.37758123761547179170e-03, +-6.26052953906250375660e-03, +-6.14057373540916311833e-03, +-6.01778262599883193018e-03, +-5.89222628815630304622e-03, +-5.76397603800424263021e-03, +-5.63310439074257793962e-03, +-5.49968502041355174204e-03, +-5.36379271917321667762e-03, +-5.22550335609255588165e-03, +-5.08489383551021401769e-03, +-4.94204205495888618943e-03, +-4.79702686268924927138e-03, +-4.64992801481256979451e-03, +-4.50082613208717050024e-03, +-4.34980265636943953800e-03, +-4.19693980675457916502e-03, +-4.04232053542952999431e-03, +-3.88602848326117904232e-03, +-3.72814793514442046479e-03, +-3.56876377513224178270e-03, +-3.40796144137293617951e-03, +-3.24582688087653560907e-03, +-3.08244650413554361137e-03, +-2.91790713962266495818e-03, +-2.75229598818970896956e-03, +-2.58570057739144132034e-03, +-2.41820871575722370558e-03, +-2.24990844703554021197e-03, +-2.08088800443330694187e-03, +-1.91123576487488202463e-03, +-1.74104020330362123901e-03, +-1.57038984704899425675e-03, +-1.39937323028345179249e-03, +-1.22807884859140337835e-03, +-1.05659511367403743075e-03, +-8.85010308212021861753e-04, +-7.13412540909905373669e-04, +-5.41889701744388552207e-04, +-3.70529417438410636591e-04, +-1.99419007184688332895e-04, +-2.86454386391723757354e-05, + 1.41704715791932274720e-04, + 3.11545322351527997646e-04, + 4.80790728994517078173e-04, + 6.49355808093498481151e-04, + 8.17155998766742235409e-04, + 9.84107348806230984584e-04, + 1.15012655618750773805e-03, + 1.31513101013778751017e-03, + 1.47903883174614527579e-03, + 1.64176891409281364154e-03, + 1.80324096188044400921e-03, + 1.96337553054683720821e-03, + 2.12209406484084378217e-03, + 2.27931893684354004020e-03, + 2.43497348341521844400e-03, + 2.58898204305202080458e-03, + 2.74126999213337996242e-03, + 2.89176378054382390501e-03, + 3.04039096665289229962e-03, + 3.18708025163550725742e-03, + 3.33176151311842744587e-03, + 3.47436583813595005824e-03, + 3.61482555538014498075e-03, + 3.75307426673132269943e-03, + 3.88904687805323055413e-03, + 4.02267962924054024026e-03, + 4.15391012350339004777e-03, + 4.28267735587738347658e-03, + 4.40892174094537157153e-03, + 4.53258513975950821928e-03, + 4.65361088595093140563e-03, + 4.77194381101678308937e-03, + 4.88753026877269871470e-03, + 5.00031815896078389583e-03, + 5.11025695000340892532e-03, + 5.21729770089245179637e-03, + 5.32139308220599526605e-03, + 5.42249739624305147206e-03, + 5.52056659626851391892e-03, + 5.61555830486112211863e-03, + 5.70743183135652247528e-03, + 5.79614818837954730302e-03, + 5.88167010745905063929e-03, + 5.96396205371965346109e-03, + 6.04299023964566684591e-03, + 6.11872263791200451943e-03, + 6.19112899327779828834e-03, + 6.26018083353982283945e-03, + 6.32585147954144774024e-03, + 6.38811605423505318724e-03, + 6.44695149079576538403e-03, + 6.50233653978409681384e-03, + 6.55425177535713839039e-03, + 6.60267960052677606309e-03, + 6.64760425146517907463e-03, + 6.68901180085764834188e-03, + 6.72689016030344512365e-03, + 6.76122908176596693758e-03, + 6.79202015807388054941e-03, + 6.81925682247539518416e-03, + 6.84293434724847406819e-03, + 6.86304984136987261678e-03, + 6.87960224724697578386e-03, + 6.89259233651607575860e-03, + 6.90202270491214152359e-03, + 6.90789776621477530361e-03, + 6.91022374527592089799e-03, + 6.90900867013538935724e-03, + 6.90426236323048170274e-03, + 6.89599643170657299052e-03, + 6.88422425683606498820e-03, + 6.86896098255334458527e-03, + 6.85022350311395231137e-03, + 6.82803044988653656810e-03, + 6.80240217728674077119e-03, + 6.77336074786231978617e-03, + 6.74092991653942995994e-03, + 6.70513511404041261804e-03, + 6.66600342948348283806e-03, + 6.62356359217582818522e-03, + 6.57784595261113724102e-03, + 6.52888246268356915031e-03, + 6.47670665513047465189e-03, + 6.42135362221612788353e-03, + 6.36285999366974046321e-03, + 6.30126391389077868121e-03, + 6.23660501843537051769e-03, + 6.16892440979760654785e-03, + 6.09826463250009130623e-03, + 6.02466964750847117777e-03, + 5.94818480598439686818e-03, + 5.86885682239295450313e-03, + 5.78673374697901473501e-03, + 5.70186493762921998985e-03, + 5.61430103113523277375e-03, + 5.52409391387439444726e-03, + 5.43129669192503241465e-03, + 5.33596366063239947036e-03, + 5.23815027364322050724e-03, + 5.13791311142524926431e-03, + 5.03530984929013124274e-03, + 4.93039922493699201561e-03, + 4.82324100553432541516e-03, + 4.71389595435920891187e-03, + 4.60242579701116046043e-03, + 4.48889318721965805553e-03, + 4.37336167226419578885e-03, + 4.25589565802507278913e-03, + 4.13656037368400047310e-03, + 4.01542183609403160321e-03, + 3.89254681383765111652e-03, + 3.76800279099204432978e-03, + 3.64185793062176202395e-03, + 3.51418103801726458557e-03, + 3.38504152369975422690e-03, + 3.25450936621163181353e-03, + 3.12265507471182202082e-03, + 2.98954965139678783756e-03, + 2.85526455376563029209e-03, + 2.71987165675057146821e-03, + 2.58344321473122102290e-03, + 2.44605182345362590079e-03, + 2.30777038187338556438e-03, + 2.16867205394239955310e-03, + 2.02883023036007446166e-03, + 1.88831849030696359050e-03, + 1.74721056318321156346e-03, + 1.60558029036844077814e-03, + 1.46350158702526116430e-03, + 1.32104840396417614300e-03, + 1.17829468959044993299e-03, + 1.03531435195189738287e-03, + 8.92181220906407453086e-04, + 7.48969010429437957559e-04, + 6.05751281079198837520e-04, + 4.62601402639519420582e-04, + 3.19592516958703328628e-04, + 1.76797501002548605557e-04, + 3.42889301410700559898e-05, +-1.07860958314116714895e-04, +-2.49580301302545907224e-04, +-3.90797645920318444633e-04, +-5.31441985020897648614e-04, +-6.71442792492634734323e-04, +-8.10730058197295030964e-04, +-9.49234322550691531593e-04, +-1.08688671073021991820e-03, +-1.22361896649146595362e-03, +-1.35936348557852870918e-03, +-1.49405334871076226656e-03, +-1.62762235413136985458e-03, +-1.76000504970118200505e-03, +-1.89113676452272319942e-03, +-2.02095364007995759864e-03, +-2.14939266087792180127e-03, +-2.27639168456901649570e-03, +-2.40188947155079574047e-03, +-2.52582571402181800535e-03, +-2.64814106448245725756e-03, +-2.76877716366639818613e-03, +-2.88767666789123715262e-03, +-3.00478327581455654377e-03, +-3.12004175458374362687e-03, +-3.23339796536792432186e-03, +-3.34479888826014811615e-03, +-3.45419264653828387429e-03, +-3.56152853027508903283e-03, +-3.66675701928568381627e-03, +-3.76982980540296712391e-03, +-3.87069981407154629915e-03, +-3.96932122525004045521e-03, +-4.06564949361390860078e-03, +-4.15964136804923296370e-03, +-4.25125491042980478001e-03, +-4.34044951367000032827e-03, +-4.42718591904522635466e-03, +-4.51142623277396223602e-03, +-4.59313394185401763226e-03, +-4.67227392914710930316e-03, +-4.74881248770633347667e-03, +-4.82271733434034600985e-03, +-4.89395762241020149813e-03, +-4.96250395385362200878e-03, +-5.02832839043272725871e-03, +-5.09140446420189209803e-03, +-5.15170718719160612709e-03, +-5.20921306030622689037e-03, +-5.26390008143260215712e-03, +-5.31574775275780748302e-03, +-5.36473708729396422251e-03, +-5.41085061460937211120e-03, +-5.45407238576448103601e-03, +-5.49438797745297521219e-03, +-5.53178449534730623527e-03, +-5.56625057664943048014e-03, +-5.59777639184752800333e-03, +-5.62635364567968653676e-03, +-5.65197557730641106377e-03, +-5.67463695969378130457e-03, +-5.69433409820978980731e-03, +-5.71106482843655206827e-03, +-5.72482851320176878984e-03, +-5.73562603883285941631e-03, +-5.74345981063785135379e-03, +-5.74833374761739290815e-03, +-5.75025327641265435880e-03, +-5.74922532449426235829e-03, +-5.74525831259774157761e-03, +-5.73836214641150563903e-03, +-5.72854820752343851104e-03, +-5.71582934363289423690e-03, +-5.70021985803501312490e-03, +-5.68173549838472177059e-03, +-5.66039344474815377811e-03, +-5.63621229694941539706e-03, +-5.60921206122125953764e-03, +-5.57941413616825417771e-03, +-5.54684129805165914567e-03, +-5.51151768540501883070e-03, +-5.47346878299080803754e-03, +-5.43272140510751410519e-03, +-5.38930367825777700136e-03, +-5.34324502318837303572e-03, +-5.29457613631248175806e-03, +-5.24332897052591333231e-03, +-5.18953671542863627375e-03, +-5.13323377696330972880e-03, +-5.07445575648276473585e-03, +-5.01323942925907713175e-03, +-4.94962272244652261993e-03, +-4.88364469251110090015e-03, +-4.81534550214015970304e-03, +-4.74476639664476486369e-03, +-4.67194967986881478511e-03, +-4.59693868961848651350e-03, +-4.51977777262569171968e-03, +-4.44051225906016977518e-03, +-4.35918843660393785094e-03, +-4.27585352410331936968e-03, +-4.19055564481250319292e-03, +-4.10334379924411681712e-03, +-4.01426783764161857621e-03, +-3.92337843208837196152e-03, +-3.83072704826951850737e-03, +-3.73636591690094466492e-03, +-3.64034800484260446379e-03, +-3.54272698590992135906e-03, +-3.44355721140094522825e-03, +-3.34289368035381060859e-03, +-3.24079200955149126021e-03, +-3.13730840328953165461e-03, +-3.03249962292274259992e-03, +-2.92642295620787733917e-03, +-2.81913618645769506812e-03, +-2.71069756152355744588e-03, +-2.60116576262271661374e-03, +-2.49059987302636997100e-03, +-2.37905934662592955658e-03, +-2.26660397639284923177e-03, +-2.15329386274948570215e-03, +-2.03918938186720523700e-03, +-1.92435115390780829905e-03, +-1.80884001122574964056e-03, +-1.69271696654636218636e-03, +-1.57604318113799030283e-03, +-1.45887993299307315576e-03, +-1.34128858503558523983e-03, +-1.22333055337022866653e-03, +-1.10506727559064096139e-03, +-9.86560179161664061245e-04, +-8.67870649892684017067e-04, +-7.49060000517653913794e-04, +-6.30189439397319385409e-04, +-5.11320039360376723744e-04, +-3.92512706698102461101e-04, +-2.73828150328942268588e-04, +-1.55326851148111989192e-04, +-3.70690315771187548660e-05, + 8.08853746707290755880e-05, + 1.98476752594946217068e-04, + 3.15645835666873892950e-04, + 4.32333735328772883737e-04, + 5.48481970218807931942e-04, + 6.64032495107181436854e-04, + 7.78927729529055225960e-04, + 8.93110586101435741449e-04, + 1.00652449850903457675e-03, + 1.11911344914620018882e-03, + 1.23082199640186964844e-03, + 1.34159530157362035657e-03, + 1.45137915539899904453e-03, + 1.56012000419063017430e-03, + 1.66776497556303743633e-03, + 1.77426190373947069608e-03, + 1.87955935442584700854e-03, + 1.98360664924133621098e-03, + 2.08635388969323877853e-03, + 2.18775198068548414054e-03, + 2.28775265355017198149e-03, + 2.38630848859077522237e-03, + 2.48337293712776532861e-03, + 2.57890034303572641614e-03, + 2.67284596376264485876e-03, + 2.76516599082240414204e-03, + 2.85581756975021973724e-03, + 2.94475881951346621368e-03, + 3.03194885136837165643e-03, + 3.11734778715522806505e-03, + 3.20091677702330967489e-03, + 3.28261801657889207284e-03, + 3.36241476344812956906e-03, + 3.44027135324883812095e-03, + 3.51615321496371192184e-03, + 3.59002688570913630964e-03, + 3.66186002489374750821e-03, + 3.73162142776055534565e-03, + 3.79928103830806575963e-03, + 3.86480996158482074943e-03, + 3.92818047535295911815e-03, + 3.98936604111683416202e-03, + 4.04834131451196205242e-03, + 4.10508215505163594206e-03, + 4.15956563522717256282e-03, + 4.21177004895932887568e-03, + 4.26167491939793193628e-03, + 4.30926100606804449861e-03, + 4.35451031136011804806e-03, + 4.39740608636303952073e-03, + 4.43793283603874291060e-03, + 4.47607632373735360443e-03, + 4.51182357505270758419e-03, + 4.54516288101758283297e-03, + 4.57608380063932208837e-03, + 4.60457716277592760817e-03, + 4.63063506735364276146e-03, + 4.65425088592728592590e-03, + 4.67541926158465074442e-03, + 4.69413610819694772369e-03, + 4.71039860901748680400e-03, + 4.72420521463094104236e-03, + 4.73555564025632692166e-03, + 4.74445086240650633347e-03, + 4.75089311490801708554e-03, + 4.75488588428478291259e-03, + 4.75643390451007622849e-03, + 4.75554315113093165057e-03, + 4.75222083476989180795e-03, + 4.74647539400918638819e-03, + 4.73831648766260323663e-03, + 4.72775498644069803317e-03, + 4.71480296401554071356e-03, + 4.69947368749087587836e-03, + 4.68178160728457970485e-03, + 4.66174234643011633356e-03, + 4.63937268930397338912e-03, + 4.61469056978682824754e-03, + 4.58771505886557909998e-03, + 4.55846635168473662131e-03, + 4.52696575405490270194e-03, + 4.49323566842705062613e-03, + 4.45729957934127077324e-03, + 4.41918203835877602265e-03, + 4.37890864848652049124e-03, + 4.33650604810387890753e-03, + 4.29200189440092326476e-03, + 4.24542484633809186906e-03, + 4.19680454713776754372e-03, + 4.14617160631750546196e-03, + 4.09355758127592610218e-03, + 4.03899495844180136256e-03, + 3.98251713399709519198e-03, + 3.92415839418544434153e-03, + 3.86395389521696766208e-03, + 3.80193964278122088427e-03, + 3.73815247117977034197e-03, + 3.67263002209005122098e-03, + 3.60541072297290579943e-03, + 3.53653376513536534670e-03, + 3.46603908146142026050e-03, + 3.39396732382294752731e-03, + 3.32035984018316321711e-03, + 3.24525865140575702286e-03, + 3.16870642778174132007e-03, + 3.09074646528776763449e-03, + 3.01142266158806225576e-03, + 2.93077949179369311866e-03, + 2.84886198399182102511e-03, + 2.76571569455873623317e-03, + 2.68138668326939897182e-03, + 2.59592148821740460393e-03, + 2.50936710055862152030e-03, + 2.42177093909172859790e-03, + 2.33318082468986958203e-03, + 2.24364495459622101392e-03, + 2.15321187659778126924e-03, + 2.06193046309074068043e-03, + 1.96984988505084042051e-03, + 1.87701958592308018950e-03, + 1.78348925544364851972e-03, + 1.68930880340843595812e-03, + 1.59452833340149326656e-03, + 1.49919811649695529192e-03, + 1.40336856494826384134e-03, + 1.30709020587860356294e-03, + 1.21041365498514362324e-03, + 1.11338959027166444805e-03, + 1.01606872582251793642e-03, + 9.18501785631088349393e-04, + 8.20739477496859018597e-04, + 7.22832467003395990300e-04, + 6.24831351591239583451e-04, + 5.26786634738466547599e-04, + 4.28748700261665177755e-04, + 3.30767786750949313850e-04, + 2.32893962150942354693e-04, + 1.35177098501164551355e-04, + 3.76668468481058423122e-05, +-5.95873876588743519559e-05, +-1.56536470474729711095e-04, +-2.53131562157722037748e-04, +-3.49324142647419787298e-04, +-4.45066035310075810549e-04, +-5.40309430740103734635e-04, +-6.35006910305014118934e-04, +-7.29111469423506203084e-04, +-8.22576540564630594166e-04, +-9.15356015957640898294e-04, +-1.00740427000084128463e-03, +-1.09867618135961594636e-03, +-1.18912715474222760448e-03, +-1.27871314234389459909e-03, +-1.36739066494837155016e-03, +-1.45511683267735177083e-03, +-1.54184936537829454448e-03, +-1.62754661264047644116e-03, +-1.71216757343079406702e-03, +-1.79567191533962417817e-03, +-1.87801999342815861480e-03, +-1.95917286866888803315e-03, +-2.03909232597019587571e-03, +-2.11774089177778042717e-03, +-2.19508185124423979562e-03, +-2.27107926495981587295e-03, +-2.34569798523625184378e-03, +-2.41890367193748701338e-03, +-2.49066280784942736815e-03, +-2.56094271358263403382e-03, +-2.62971156200168766290e-03, +-2.69693839217458606120e-03, +-2.76259312283697608739e-03, +-2.82664656536508410861e-03, +-2.88907043625251033769e-03, +-2.94983736908550680730e-03, +-3.00892092601204481916e-03, +-3.06629560870052934873e-03, +-3.12193686878331445531e-03, +-3.17582111778177576464e-03, +-3.22792573650879186659e-03, +-3.27822908394535990351e-03, +-3.32671050558861836413e-03, +-3.37335034126782541686e-03, +-3.41812993242640843911e-03, +-3.46103162886747485125e-03, +-3.50203879496072990885e-03, +-3.54113581530953033458e-03, +-3.57830809987640932265e-03, +-3.61354208856588636489e-03, +-3.64682525526394910736e-03, +-3.67814611133359227815e-03, +-3.70749420856602597552e-03, +-3.73486014158783824479e-03, +-3.76023554972410066835e-03, +-3.78361311831824139590e-03, +-3.80498657950949356263e-03, +-3.82435071246891309174e-03, +-3.84170134309564249159e-03, +-3.85703534317483227867e-03, +-3.87035062899941184958e-03, +-3.88164615945781315415e-03, +-3.89092193359018290177e-03, +-3.89817898761586753217e-03, +-3.90341939143522623223e-03, +-3.90664624460901419717e-03, +-3.90786367181894002398e-03, +-3.90707681781324485393e-03, +-3.90429184184126710708e-03, +-3.89951591158146492616e-03, +-3.89275719656733548701e-03, +-3.88402486111620462786e-03, +-3.87332905676572971168e-03, +-3.86068091422367464308e-03, +-3.84609253483633988652e-03, +-3.82957698158139896172e-03, +-3.81114826959133828205e-03, +-3.79082135621343309026e-03, +-3.76861213061301580582e-03, +-3.74453740292646350060e-03, +-3.71861489297091191847e-03, +-3.69086321851783442580e-03, +-3.66130188313754665122e-03, +-3.62995126362247863203e-03, +-3.59683259699652849509e-03, +-3.56196796711877707378e-03, +-3.52538029088927777621e-03, +-3.48709330406542271710e-03, +-3.44713154669716278014e-03, +-3.40552034818984500006e-03, +-3.36228581200323853317e-03, +-3.31745479999584480524e-03, +-3.27105491642360043589e-03, +-3.22311449160199306810e-03, +-3.17366256524132884023e-03, +-3.12272886946435550976e-03, +-3.07034381151609402430e-03, +-3.01653845617577253541e-03, +-2.96134450788043245700e-03, +-2.90479429257073850854e-03, +-2.84692073926870632683e-03, +-2.78775736139794984292e-03, +-2.72733823785672839513e-03, +-2.66569799385409870324e-03, +-2.60287178151993913236e-03, +-2.53889526029965357373e-03, +-2.47380457714372692726e-03, +-2.40763634650355490621e-03, +-2.34042763014413865083e-03, +-2.27221591678447533066e-03, +-2.20303910157702452152e-03, +-2.13293546543681959357e-03, +-2.06194365423175264909e-03, +-1.99010265784496783933e-03, +-1.91745178912041433321e-03, +-1.84403066270314016858e-03, +-1.76987917378504866148e-03, +-1.69503747676780160310e-03, +-1.61954596385395933195e-03, +-1.54344524357734455208e-03, +-1.46677611928450082716e-03, +-1.38957956757772282952e-03, +-1.31189671673156917249e-03, +-1.23376882509377769348e-03, +-1.15523725948148982788e-03, +-1.07634347358468449377e-03, +-9.97128986387143959394e-04, +-9.17635360616648500243e-04, +-8.37904181234895789956e-04, +-7.57977033978787513406e-04, +-6.77895483963235779418e-04, +-5.97701054357152421204e-04, +-5.17435205142649512489e-04, +-4.37139311968777596797e-04, +-3.56854645110210024969e-04, +-2.76622348541154185371e-04, +-1.96483419135612727945e-04, +-1.16478686003570469231e-04, +-3.66487899740422618075e-05, + 4.29658367651341511670e-05, + 1.22324990860946911401e-04, + 2.01388717811737909388e-04, + 2.80117331797544979934e-04, + 3.58471435313892643378e-04, + 4.36411938600040889922e-04, + 5.13900078851591240840e-04, + 5.90897439209055901944e-04, + 6.67365967512406946770e-04, + 7.43267994812951346417e-04, + 8.18566253633950927961e-04, + 8.93223895970637264512e-04, + 9.67204511021861590946e-04, + 1.04047214264425358192e-03, + 1.11299130652140420249e-03, + 1.18472700703946731866e-03, + 1.25564475386154045418e-03, + 1.32571057819342382096e-03, + 1.39489104873262805863e-03, + 1.46315328729405358735e-03, + 1.53046498410463441449e-03, + 1.59679441276025036248e-03, + 1.66211044483838841015e-03, + 1.72638256415947395801e-03, + 1.78958088069116868016e-03, + 1.85167614408905580742e-03, + 1.91263975686785663195e-03, + 1.97244378719760738577e-03, + 2.03106098131931389963e-03, + 2.08846477557452425353e-03, + 2.14462930804391795764e-03, + 2.19952942979019039696e-03, + 2.25314071570019555310e-03, + 2.30543947492238164229e-03, + 2.35640276089497556142e-03, + 2.40600838096100867747e-03, + 2.45423490556669890092e-03, + 2.50106167703914496897e-03, + 2.54646881794065452556e-03, + 2.59043723899601840976e-03, + 2.63294864659046256791e-03, + 2.67398554983521103204e-03, + 2.71353126719851020857e-03, + 2.75156993270003411012e-03, + 2.78808650166653335112e-03, + 2.82306675604716231925e-03, + 2.85649730928709153985e-03, + 2.88836561075816750793e-03, + 2.91865994974546466220e-03, + 2.94736945898928888107e-03, + 2.97448411778179853254e-03, + 2.99999475461813899443e-03, + 3.02389304940205334848e-03, + 3.04617153520601608579e-03, + 3.06682359958635559691e-03, + 3.08584348545404892755e-03, + 3.10322629150200672218e-03, + 3.11896797218987227585e-03, + 3.13306533728775369815e-03, + 3.14551605098039102626e-03, + 3.15631863053354591933e-03, + 3.16547244452441024071e-03, + 3.17297771063858400492e-03, + 3.17883549303571563346e-03, + 3.18304769928660826611e-03, + 3.18561707688456985377e-03, + 3.18654720933417290318e-03, + 3.18584251182050994661e-03, + 3.18350822646264360050e-03, + 3.17955041715474407901e-03, + 3.17397596399888754642e-03, + 3.16679255733362226624e-03, + 3.15800869136252529770e-03, + 3.14763365738724267343e-03, + 3.13567753664971719460e-03, + 3.12215119278838691003e-03, + 3.10706626391348732577e-03, + 3.09043515430657261128e-03, + 3.07227102574976181429e-03, + 3.05258778849025729646e-03, + 3.03140009184578061371e-03, + 3.00872331445699433758e-03, + 2.98457355419296660459e-03, + 2.95896761771581541176e-03, + 2.93192300971099667137e-03, + 2.90345792178986830678e-03, + 2.87359122107115833381e-03, + 2.84234243844815569202e-03, + 2.80973175654865899714e-03, + 2.77577999739489662823e-03, + 2.74050860977057735360e-03, + 2.70393965630238552328e-03, + 2.66609580026378606421e-03, + 2.62700029210837524354e-03, + 2.58667695574077254050e-03, + 2.54515017453282822377e-03, + 2.50244487709332368713e-03, + 2.45858652279897166651e-03, + 2.41360108709495107052e-03, + 2.36751504657360840878e-03, + 2.32035536383917847733e-03, + 2.27214947216734537011e-03, + 2.22292525996793232518e-03, + 2.17271105505975571301e-03, + 2.12153560876561335380e-03, + 2.06942807983705873154e-03, + 2.01641801821680422338e-03, + 1.96253534864859182849e-03, + 1.90781035414268307880e-03, + 1.85227365930619859540e-03, + 1.79595621354771339470e-03, + 1.73888927416449511586e-03, + 1.68110438932177089048e-03, + 1.62263338093348468728e-03, + 1.56350832745304072283e-03, + 1.50376154658367453161e-03, + 1.44342557791726690958e-03, + 1.38253316551135724960e-03, + 1.32111724041281413007e-03, + 1.25921090313770521994e-03, + 1.19684740611688275949e-03, + 1.13406013611574898320e-03, + 1.07088259663794954646e-03, + 1.00734839032173340879e-03, + 9.43491201338451197442e-04, + 8.79344777802133358187e-04, + 8.14942914198997676867e-04, + 7.50319433846045077789e-04, + 6.85508171388117602645e-04, + 6.20542955341616764633e-04, + 5.55457590694125209752e-04, + 4.90285841569116395515e-04, + 4.25061413963795440944e-04, + 3.59817938569106346609e-04, + 2.94588953680933085706e-04, + 2.29407888210245771441e-04, + 1.64308044801349289110e-04, + 9.93225830661220992091e-05, + 3.44845029432159748818e-05, +-3.01733718103322993271e-05, +-9.46184099865878051579e-05, +-1.58818189144901994068e-04, +-2.22740511673599295237e-04, +-2.86353420686933518319e-04, +-3.49625215749474168095e-04, +-4.12524468420490651472e-04, +-4.75020037611034338584e-04, +-5.37081084745966554420e-04, +-5.98677088724102000189e-04, +-6.59777860668749548644e-04, +-7.20353558462378845868e-04, +-7.80374701058222453379e-04, +-8.39812182561741876058e-04, +-8.98637286076072534964e-04, +-9.56821697304657218380e-04, +-1.01433751790445296839e-03, +-1.07115727858425125243e-03, +-1.12725395194157021125e-03, +-1.18260096503265514645e-03, +-1.23717221166938983953e-03, +-1.29094206443821453087e-03, +-1.34388538643541812813e-03, +-1.39597754271321623266e-03, +-1.44719441143244622640e-03, +-1.49751239471598309415e-03, +-1.54690842919921311277e-03, +-1.59535999627203944548e-03, +-1.64284513200888535912e-03, +-1.68934243678199938477e-03, +-1.73483108455441971917e-03, +-1.77929083184826127527e-03, +-1.82270202638530284291e-03, +-1.86504561539608984359e-03, +-1.90630315359404723698e-03, +-1.94645681081197273812e-03, +-1.98548937929780454012e-03, +-2.02338428066662365593e-03, +-2.06012557250690765687e-03, +-2.09569795463821536424e-03, +-2.13008677501847496286e-03, +-2.16327803529848140124e-03, +-2.19525839602226170363e-03, +-2.22601518147149193827e-03, +-2.25553638415244925991e-03, +-2.28381066892440051305e-03, +-2.31082737676846549160e-03, +-2.33657652819600639496e-03, +-2.36104882629574550773e-03, +-2.38423565941946538627e-03, +-2.40612910350581450311e-03, +-2.42672192404203967281e-03, +-2.44600757766397268814e-03, +-2.46398021339438002067e-03, +-2.48063467352028057047e-03, +-2.49596649410964519650e-03, +-2.50997190516864723125e-03, +-2.52264783044025284534e-03, +-2.53399188684540720151e-03, +-2.54400238356825665262e-03, +-2.55267832078691359055e-03, +-2.56001938805160448795e-03, +-2.56602596231194192769e-03, +-2.57069910559561132235e-03, +-2.57404056234069840772e-03, +-2.57605275638400242275e-03, +-2.57673878760806066013e-03, +-2.57610242824962915389e-03, +-2.57414811887259368725e-03, +-2.57088096400836900457e-03, +-2.56630672746716416779e-03, +-2.56043182732341697075e-03, +-2.55326333057917390437e-03, +-2.54480894750897836121e-03, +-2.53507702569032763312e-03, +-2.52407654372365647388e-03, +-2.51181710464612895778e-03, +-2.49830892904353337597e-03, +-2.48356284786475705814e-03, +-2.46759029494360467016e-03, +-2.45040329923257435216e-03, +-2.43201447675357512387e-03, +-2.41243702227060758184e-03, +-2.39168470068965325834e-03, +-2.36977183819085321370e-03, +-2.34671331309871259233e-03, +-2.32252454649548413859e-03, +-2.29722149258377488293e-03, +-2.27082062880380698353e-03, +-2.24333894571130537665e-03, +-2.21479393662223902547e-03, +-2.18520358703003540410e-03, +-2.15458636380176215414e-03, +-2.12296120415960722083e-03, +-2.09034750445369690852e-03, +-2.05676510873303809365e-03, +-2.02223429712087166693e-03, +-1.98677577400132665889e-03, +-1.95041065602380068143e-03, +-1.91316045993188566660e-03, +-1.87504709022398054208e-03, +-1.83609282665202818569e-03, +-1.79632031156571974305e-03, +-1.75575253710894539118e-03, +-1.71441283227574312563e-03, +-1.67232484983291908656e-03, +-1.62951255311622692640e-03, +-1.58600020270752910083e-03, +-1.54181234300042021082e-03, +-1.49697378866114633872e-03, +-1.45150961099237444871e-03, +-1.40544512420743054025e-03, +-1.35880587162187237323e-03, +-1.31161761177006727826e-03, +-1.26390630445442453227e-03, +-1.21569809673418671551e-03, +-1.16701930886166653674e-03, +-1.11789642017300181083e-03, +-1.06835605494137557414e-03, +-1.01842496819956130141e-03, +-9.68130031539442812739e-04, +-9.17498218896290623249e-04, +-8.66556592324564493868e-04, +-8.15332287772978616183e-04, +-7.63852500866257408917e-04, +-7.12144472700820384964e-04, +-6.60235475661517237297e-04, +-6.08152799267011124132e-04, +-5.55923736050680200420e-04, +-5.03575567484773503439e-04, +-4.51135549954315671906e-04, +-3.98630900788171399930e-04, +-3.46088784354618185513e-04, +-2.93536298227804867602e-04, +-2.41000459432347881880e-04, +-1.88508190773214112049e-04, +-1.36086307257084302303e-04, +-8.37615026124415208318e-05, +-3.15603359146758591044e-05, + 2.04907816767023618287e-05, + 7.23656000628412833693e-05, + 1.24038043225600054433e-04, + 1.75482222116205200833e-04, + 2.26672447407071596913e-04, + 2.77583242099614419147e-04, + 3.28189353983021332804e-04, + 3.78465767937005519422e-04, + 4.28387718073507952569e-04, + 4.77930699711027453993e-04, + 5.27070481176294264314e-04, + 5.75783115427220041314e-04, + 6.24044951492278227381e-04, + 6.71832645720683982113e-04, + 7.19123172837888647094e-04, + 7.65893836801815361230e-04, + 8.12122281454607207463e-04, + 8.57786500964706813931e-04, + 9.02864850055145489773e-04, + 9.47336054012924352885e-04, + 9.91179218475344821562e-04, + 1.03437383898850724685e-03, + 1.07689981033424705438e-03, + 1.11873743562118156160e-03, + 1.15986743513579325555e-03, + 1.20027095494985164281e-03, + 1.23992957528063201672e-03, + 1.27882531860024116835e-03, + 1.31694065749045157408e-03, + 1.35425852224024464987e-03, + 1.39076230818266951932e-03, + 1.42643588276789089024e-03, + 1.46126359237003949389e-03, + 1.49523026882479484305e-03, + 1.52832123569547530945e-03, + 1.56052231426488533308e-03, + 1.59181982925111196493e-03, + 1.62220061424500194142e-03, + 1.65165201686719317030e-03, + 1.68016190364333106375e-03, + 1.70771866459552704512e-03, + 1.73431121754877184786e-03, + 1.75992901215076880984e-03, + 1.78456203360429659956e-03, + 1.80820080611094821665e-03, + 1.83083639602529585529e-03, + 1.85246041471891220720e-03, + 1.87306502115368290161e-03, + 1.89264292416397640097e-03, + 1.91118738444732896159e-03, + 1.92869221626372814270e-03, + 1.94515178884347187879e-03, + 1.96056102750367033591e-03, + 1.97491541447399011552e-03, + 1.98821098943195847739e-03, + 2.00044434974860733945e-03, + 2.01161265044509608366e-03, + 2.02171360386141883703e-03, + 2.03074547903829647627e-03, + 2.03870710081329245544e-03, + 2.04559784863279697439e-03, + 2.05141765508121132200e-03, + 2.05616700412915255278e-03, + 2.05984692910230610119e-03, + 2.06245901037309994214e-03, + 2.06400537277705341602e-03, + 2.06448868275625058155e-03, + 2.06391214523207744413e-03, + 2.06227950020990537586e-03, + 2.05959501911819184081e-03, + 2.05586350088483903534e-03, + 2.05109026775365885925e-03, + 2.04528116084394225374e-03, + 2.03844253545626581670e-03, + 2.03058125612778830188e-03, + 2.02170469144040887075e-03, + 2.01182070858521491047e-03, + 2.00093766768695948202e-03, + 1.98906441589210680049e-03, + 1.97621028122438920777e-03, + 1.96238506621177182659e-03, + 1.94759904128888393197e-03, + 1.93186293797900990321e-03, + 1.91518794185986402506e-03, + 1.89758568531769714928e-03, + 1.87906824009385019746e-03, + 1.85964810962852347687e-03, + 1.83933822120627122297e-03, + 1.81815191790804173144e-03, + 1.79610295037441560807e-03, + 1.77320546838494034515e-03, + 1.74947401225873200130e-03, + 1.72492350408103120758e-03, + 1.69956923876105037673e-03, + 1.67342687492632539309e-03, + 1.64651242565860508361e-03, + 1.61884224907680703345e-03, + 1.59043303877220510226e-03, + 1.56130181410158168538e-03, + 1.53146591034349164456e-03, + 1.50094296872333799256e-03, + 1.46975092631300560328e-03, + 1.43790800581038743892e-03, + 1.40543270520465083014e-03, + 1.37234378733301696889e-03, + 1.33866026933477191320e-03, + 1.30440141200818598630e-03, + 1.26958670907636713213e-03, + 1.23423587636767762184e-03, + 1.19836884091695044206e-03, + 1.16200572999298904278e-03, + 1.12516686005846404395e-03, + 1.08787272566834868938e-03, + 1.05014398831246302812e-03, + 1.01200146520824866246e-03, + 9.73466118049983288388e-04, + 9.34559041719948196611e-04, + 8.95301452967915711335e-04, + 8.55714679064593008659e-04, + 8.15820146435422468428e-04, + 7.75639369280203805866e-04, + 7.35193938184691589237e-04, + 6.94505508730360781103e-04, + 6.53595790107610935191e-04, + 6.12486533739071471218e-04, + 5.71199521918073420228e-04, + 5.29756556468897262142e-04, + 4.88179447433947737416e-04, + 4.46490001794050709802e-04, + 4.04710012227305993091e-04, + 3.62861245912609686835e-04, + 3.20965433382992511909e-04, + 2.79044257434640438631e-04, + 2.37119342097372800019e-04, + 1.95212241671636533603e-04, + 1.53344429837704167947e-04, + 1.11537288842718541599e-04, + 6.98120987704314377789e-05, + 2.81900268993452554395e-05, +-1.33078828458379828427e-05, +-5.46607203438825674300e-05, +-9.58477196232063128950e-05, +-1.36848269099311073286e-04, +-1.77641921698430010380e-04, +-2.18208404862630192013e-04, +-2.58527630431676846631e-04, +-2.98579704396867049668e-04, +-3.38344936521953437280e-04, +-3.77803849827058782322e-04, +-4.16937189930904319925e-04, +-4.55725934246739843459e-04, +-4.94151301028182598010e-04, +-5.32194758260364701556e-04, +-5.69838032392598397777e-04, +-6.07063116908156791794e-04, +-6.43852280727741713151e-04, +-6.80188076442613171781e-04, +-7.16053348373450011463e-04, +-7.51431240451819475352e-04, +-7.86305203920363614614e-04, +-8.20659004848588277854e-04, +-8.54476731460626398769e-04, +-8.87742801272211191736e-04, +-9.20441968033579760618e-04, +-9.52559328475276884118e-04, +-9.84080328854130366098e-04, +-1.01499077129671671886e-03, +-1.04527681993767346084e-03, +-1.07492500685012399610e-03, +-1.10392223776622968451e-03, +-1.13225579758538573774e-03, +-1.15991335566776048067e-03, +-1.18688297091152023324e-03, +-1.21315309661150744040e-03, +-1.23871258509778933189e-03, +-1.26355069215218973264e-03, +-1.28765708120147479195e-03, +-1.31102182728572635648e-03, +-1.33363542080036233568e-03, +-1.35548877101096445358e-03, +-1.37657320933958870861e-03, +-1.39688049242180935793e-03, +-1.41640280493340441764e-03, +-1.43513276218638474030e-03, +-1.45306341249334513427e-03, +-1.47018823930013145355e-03, +-1.48650116308605430814e-03, +-1.50199654303180877256e-03, +-1.51666917845484855790e-03, +-1.53051431001215848537e-03, +-1.54352762067077827791e-03, +-1.55570523644627803014e-03, +-1.56704372690943645810e-03, +-1.57754010546188694168e-03, +-1.58719182938115940286e-03, +-1.59599679963599232028e-03, +-1.60395336047266818397e-03, +-1.61106029877347285521e-03, +-1.61731684318832920691e-03, +-1.62272266304074063749e-03, +-1.62727786700950075895e-03, +-1.63098300158752559583e-03, +-1.63383904931938927878e-03, +-1.63584742681915007098e-03, +-1.63700998257036147918e-03, +-1.63732899451001076216e-03, +-1.63680716739846910703e-03, +-1.63544762997745404300e-03, +-1.63325393191824947553e-03, +-1.63023004056244216753e-03, +-1.62638033745757639228e-03, +-1.62170961469021174955e-03, +-1.61622307101895478811e-03, +-1.60992630781018361379e-03, +-1.60282532477918769794e-03, +-1.59492651553961163439e-03, +-1.58623666296416683703e-03, +-1.57676293435965995428e-03, +-1.56651287645941865272e-03, +-1.55549441023637930251e-03, +-1.54371582554013535814e-03, +-1.53118577556127515200e-03, +-1.51791327112649242562e-03, +-1.50390767482801038582e-03, +-1.48917869499094052133e-03, +-1.47373637948217746547e-03, +-1.45759110936466060836e-03, +-1.44075359240074425682e-03, +-1.42323485640868073465e-03, +-1.40504624247599204864e-03, +-1.38619939803382081524e-03, +-1.36670626979641294217e-03, +-1.34657909656966815262e-03, +-1.32583040193301449593e-03, +-1.30447298679896685550e-03, +-1.28251992185438013459e-03, +-1.25998453988795662377e-03, +-1.23688042800817435581e-03, +-1.21322141975630610686e-03, +-1.18902158711867676766e-03, +-1.16429523244280098797e-03, +-1.13905688026204581637e-03, +-1.11332126903301116203e-03, +-1.08710334279067352171e-03, +-1.06041824272541424130e-03, +-1.03328129868704887868e-03, +-1.00570802062011207742e-03, +-9.77714089935322180555e-04, +-9.49315350821759501229e-04, +-9.20527801504691478400e-04, +-8.91367585453492765508e-04, +-8.61850982544499480062e-04, +-8.31994400183724228809e-04, +-8.01814364393843201882e-04, +-7.71327510870362977047e-04, +-7.40550576011879011992e-04, +-7.09500387928816301369e-04, +-6.78193857435692871310e-04, +-6.46647969031396334730e-04, +-6.14879771872516131710e-04, +-5.82906370744061324771e-04, +-5.50744917032461615489e-04, +-5.18412599705563741960e-04, +-4.85926636304230086336e-04, +-4.53304263950078342206e-04, +-4.20562730374023118537e-04, +-3.87719284970423796848e-04, +-3.54791169881019867287e-04, +-3.21795611113349097968e-04, +-2.88749809698345409788e-04, +-2.55670932891157169815e-04, +-2.22576105419946933131e-04, +-1.89482400786797724242e-04, +-1.56406832625384566377e-04, +-1.23366346119315335164e-04, +-9.03778094855688048136e-05, +-5.74580055274082543144e-05, +-2.46236232605249242254e-05, + 8.10875038316639484403e-06, + 4.07226387702898438674e-05, + 7.32016836950174766508e-05, + 1.05529653418793463730e-04, + 1.37690450616703013997e-04, + 1.69668120226623675949e-04, + 2.01446857197505152211e-04, + 2.33011014133184106998e-04, + 2.64345108828066273181e-04, + 2.95433831690941053547e-04, + 3.26262053053821875562e-04, + 3.56814830362236329840e-04, + 3.87077415243466558745e-04, + 4.17035260449873101951e-04, + 4.46674026673809685620e-04, + 4.75979589231274630330e-04, + 5.04938044610982032269e-04, + 5.33535716886269443388e-04, + 5.61759163986835612092e-04, + 5.89595183827354429873e-04, + 6.17030820290651992738e-04, + 6.44053369062530110985e-04, + 6.70650383315962803771e-04, + 6.96809679241917109133e-04, + 7.22519341424928177552e-04, + 7.47767728060641924219e-04, + 7.72543476013702731450e-04, + 7.96835505713403631674e-04, + 8.20633025885535226200e-04, + 8.43925538118381487161e-04, + 8.66702841260924973336e-04, + 8.88955035651854165446e-04, + 9.10672527177615212350e-04, + 9.31846031157871484973e-04, + 9.52466576057239681409e-04, + 9.72525507021732124775e-04, + 9.92014489238877755425e-04, + 1.01092551112014119447e-03, + 1.02925088730489687483e-03, + 1.04698326148487523037e-03, + 1.06411560904814419225e-03, + 1.08064123954212140503e-03, + 1.09655379895474709012e-03, + 1.11184727181350227060e-03, + 1.12651598310145530275e-03, + 1.14055459999043234086e-03, + 1.15395813339070935251e-03, + 1.16672193931725690953e-03, + 1.17884172007230573521e-03, + 1.19031352524443380207e-03, + 1.20113375252423222606e-03, + 1.21129914833666986994e-03, + 1.22080680829065105208e-03, + 1.22965417744607123825e-03, + 1.23783905039882846655e-03, + 1.24535957118451323482e-03, + 1.25221423300135711529e-03, + 1.25840187775329488164e-03, + 1.26392169541390537828e-03, + 1.26877322321232639292e-03, + 1.27295634464211107444e-03, + 1.27647128829414154005e-03, + 1.27931862651490548498e-03, + 1.28149927389138891531e-03, + 1.28301448556399880392e-03, + 1.28386585536898346210e-03, + 1.28405531381196435364e-03, + 1.28358512587416814105e-03, + 1.28245788865312404514e-03, + 1.28067652883962455890e-03, + 1.27824430003284665244e-03, + 1.27516477989559045420e-03, + 1.27144186715168476705e-03, + 1.26707977842766580760e-03, + 1.26208304494093768826e-03, + 1.25645650903666696377e-03, + 1.25020532057574596321e-03, + 1.24333493317623205304e-03, + 1.23585110031071486285e-03, + 1.22775987126220184967e-03, + 1.21906758694106096864e-03, + 1.20978087556570016413e-03, + 1.19990664820977745338e-03, + 1.18945209421860830651e-03, + 1.17842467649774342194e-03, + 1.16683212667649549056e-03, + 1.15468244014949755240e-03, + 1.14198387099919015063e-03, + 1.12874492680236585690e-03, + 1.11497436332383317165e-03, + 1.10068117910044980384e-03, + 1.08587460991860403070e-03, + 1.07056412318845268865e-03, + 1.05475941221827552129e-03, + 1.03847039039213777552e-03, + 1.02170718525430208670e-03, + 1.00448013250386408712e-03, + 9.86799769902908796571e-04, + 9.68676831101775311604e-04, + 9.50122239384842536686e-04, + 9.31147101340516931967e-04, + 9.11762700458799784341e-04, + 8.91980490660106628206e-04, + 8.71812089758989324645e-04, + 8.51269272866356447108e-04, + 8.30363965733769732354e-04, + 8.09108238043540397427e-04, + 7.87514296648406260902e-04, + 7.65594478764287304610e-04, + 7.43361245119910263486e-04, + 7.20827173067144330761e-04, + 6.98004949655533580080e-04, + 6.74907364674943543829e-04, + 6.51547303669901115876e-04, + 6.27937740929578719871e-04, + 6.04091732456894250046e-04, + 5.80022408920566161228e-04, + 5.55742968593996586671e-04, + 5.31266670284408345712e-04, + 5.06606826256191336046e-04, + 4.81776795151971288286e-04, + 4.56789974915332633570e-04, + 4.31659795718581772855e-04, + 4.06399712899354833857e-04, + 3.81023199909761244551e-04, + 3.55543741281616379035e-04, + 3.29974825611307478416e-04, + 3.04329938567904757871e-04, + 2.78622555928232935440e-04, + 2.52866136642138929734e-04, + 2.27074115931597155090e-04, + 2.01259898427254919819e-04, + 1.75436851345555256277e-04, + 1.49618297710086417540e-04, + 1.23817509620332964109e-04, + 9.80477015714136803867e-05, + 7.23220238277867656044e-05, + 4.66535558543199922808e-05, + 2.10552998080745397132e-05, +-4.45982590633637267685e-06, +-2.98789930144383005840e-05, +-5.51894696797388301145e-05, +-8.03786267385361320997e-05, +-1.05433943858796803006e-04, +-1.30343015620240231141e-04, +-1.55093557512704107414e-04, +-1.79673411849813922459e-04, +-2.04070553595469639328e-04, +-2.28273096100298591472e-04, +-2.52269296745275168909e-04, +-2.76047562490193821964e-04, +-2.99596455324310003560e-04, +-3.22904697616543522477e-04, +-3.45961177363105203825e-04, +-3.68754953329960058744e-04, +-3.91275260088006534946e-04, +-4.13511512938510329696e-04, +-4.35453312726917203881e-04, +-4.57090450542803317623e-04, +-4.78412912303817451296e-04, +-4.99410883221915679296e-04, +-5.20074752149766658671e-04, +-5.40395115805737333292e-04, +-5.60362782875298238647e-04, +-5.79968777987699369778e-04, +-5.99204345565891864818e-04, +-6.18060953548384053174e-04, +-6.36530296981365232775e-04, +-6.54604301479925370678e-04, +-6.72275126556943374879e-04, +-6.89535168818290744586e-04, +-7.06377065023390971615e-04, +-7.22793695009926024340e-04, +-7.38778184481572101731e-04, +-7.54323907658020135873e-04, +-7.69424489786242268852e-04, +-7.84073809512324942927e-04, +-7.98266001112985629749e-04, +-8.11995456586320977881e-04, +-8.25256827601124256372e-04, +-8.38045027304191287275e-04, +-8.50355231985365717443e-04, +-8.62182882599891249782e-04, +-8.73523686147764872115e-04, +-8.84373616909959786754e-04, +-8.94728917541413090037e-04, +-9.04586100020679756244e-04, +-9.13941946456355816704e-04, +-9.22793509750267264627e-04, +-9.31138114117751138944e-04, +-9.38973355465201283722e-04, +-9.46297101625169024067e-04, +-9.53107492449534513500e-04, +-9.59402939761150449702e-04, +-9.65182127164483996684e-04, +-9.70444009715949393313e-04, +-9.75187813454562795953e-04, +-9.79413034793723616400e-04, +-9.83119439774883139768e-04, +-9.86307063184082167401e-04, +-9.88976207532291833394e-04, +-9.91127441900544869230e-04, +-9.92761600651050806279e-04, +-9.93879782005378667811e-04, +-9.94483346490992797459e-04, +-9.94573915257405570187e-04, +-9.94153368263331295093e-04, +-9.93223842336246652909e-04, +-9.91787729105850180897e-04, +-9.89847672812951264940e-04, +-9.87406567995411906316e-04, +-9.84467557052782528404e-04, +-9.81034027691367847834e-04, +-9.77109610251477699733e-04, +-9.72698174918703792335e-04, +-9.67803828821115733234e-04, +-9.62430913014279427325e-04, +-9.56583999356122919276e-04, +-9.50267887273650141942e-04, +-9.43487600423628257514e-04, +-9.36248383249343269982e-04, +-9.28555697435622562526e-04, +-9.20415218264345998470e-04, +-9.11832830872733794518e-04, +-9.02814626416679100358e-04, +-8.93366898141493941121e-04, +-8.83496137362504399722e-04, +-8.73209029357859358757e-04, +-8.62512449176020662943e-04, +-8.51413457360529739998e-04, +-8.39919295594453380396e-04, +-8.28037382267176572288e-04, +-8.15775307966064137412e-04, +-8.03140830895733765817e-04, +-7.90141872227454497395e-04, +-7.76786511381427125823e-04, +-7.63082981244709722575e-04, +-7.49039663327390583050e-04, +-7.34665082859875225377e-04, +-7.19967903833961626534e-04, +-7.04956923990644160512e-04, +-6.89641069757283018196e-04, +-6.74029391137054853869e-04, +-6.58131056553546409972e-04, +-6.41955347653322514097e-04, +-6.25511654069284880192e-04, +-6.08809468147721304272e-04, +-5.91858379642030605315e-04, +-5.74668070375839888306e-04, +-5.57248308878482566560e-04, +-5.39608944995842118066e-04, +-5.21759904479256251923e-04, +-5.03711183555554655941e-04, +-4.85472843480994986718e-04, +-4.67055005082172224832e-04, +-4.48467843286585717087e-04, +-4.29721581645848931235e-04, +-4.10826486854523479156e-04, +-3.91792863267230776457e-04, +-3.72631047417096349181e-04, +-3.53351402538234474118e-04, +-3.33964313095238879339e-04, +-3.14480179322441726845e-04, +-2.94909411775696268711e-04, +-2.75262425899514299663e-04, +-2.55549636612443630684e-04, +-2.35781452913229664075e-04, +-2.15968272510589943134e-04, +-1.96120476479425779204e-04, +-1.76248423945933802622e-04, +-1.56362446804383454146e-04, +-1.36472844468305155993e-04, +-1.16589878658458767635e-04, +-9.67237682303544415822e-05, +-7.68846840437216406863e-05, +-5.70827438766376965410e-05, +-3.73280073865603565495e-05, +-1.76304711208225556719e-05, + 1.99993642088864226016e-06, + 2.15533596699292954036e-05, + 4.10200208154242509364e-05, + 6.03902245722433725860e-05, + 7.96543628875890849517e-05, + 9.88029195844659414733e-05, + 1.17826474939476195025e-04, + 1.36715710193023647035e-04, + 1.55461411989631342456e-04, + 1.74054476746553134919e-04, + 1.92485914948569894868e-04, + 2.10746855366906229437e-04, + 2.28828549200575789499e-04, + 2.46722374138184409598e-04, + 2.64419838338276027342e-04, + 2.81912584326679917842e-04, + 2.99192392808960154656e-04, + 3.16251186396444155819e-04, + 3.33081033244039836395e-04, + 3.49674150598494463179e-04, + 3.66022908255491080231e-04, + 3.82119831924034101915e-04, + 3.97957606496917735885e-04, + 4.13529079225828470872e-04, + 4.28827262799762372065e-04, + 4.43845338325564724331e-04, + 4.58576658209470361914e-04, + 4.73014748938412597258e-04, + 4.87153313760160528844e-04, + 5.00986235261103489760e-04, + 5.14507577840937952753e-04, + 5.27711590083254872101e-04, + 5.40592707021128712937e-04, + 5.53145552297087950144e-04, + 5.65364940216665540391e-04, + 5.77245877694797693454e-04, + 5.88783566094626962042e-04, + 5.99973402958039613193e-04, + 6.10810983627539487439e-04, + 6.21292102758916895203e-04, + 6.31412755724494408928e-04, + 6.41169139906554250846e-04, + 6.50557655880656818606e-04, + 6.59574908488803728079e-04, + 6.68217707802125100019e-04, + 6.76483069973211437013e-04, + 6.84368217977891248049e-04, + 6.91870582246639927691e-04, + 6.98987801185634960270e-04, + 7.05717721587660520161e-04, + 7.12058398933015208009e-04, + 7.18008097580767590783e-04, + 7.23565290850654123378e-04, + 7.28728660995954687085e-04, + 7.33497099067867354590e-04, + 7.37869704671835252748e-04, + 7.41845785616332496076e-04, + 7.45424857454791262544e-04, + 7.48606642921267949158e-04, + 7.51391071260577316469e-04, + 7.53778277453638493114e-04, + 7.55768601338868977087e-04, + 7.57362586630487056617e-04, + 7.58560979834606492235e-04, + 7.59364729064121901821e-04, + 7.59774982753388386167e-04, + 7.59793088273752925850e-04, + 7.59420590451042459845e-04, + 7.58659229986178283191e-04, + 7.57510941780111337653e-04, + 7.55977853164323059486e-04, + 7.54062282038194995303e-04, + 7.51766734914572948463e-04, + 7.49093904874909206383e-04, + 7.46046669435407165151e-04, + 7.42628088325620098163e-04, + 7.38841401181018265533e-04, + 7.34690025151058076665e-04, + 7.30177552424332988561e-04, + 7.25307747672431467334e-04, + 7.20084545414128533031e-04, + 7.14512047301645285974e-04, + 7.08594519330652482768e-04, + 7.02336388975790940938e-04, + 6.95742242253507572024e-04, + 6.88816820714019178648e-04, + 6.81565018364235775117e-04, + 6.73991878523528100201e-04, + 6.66102590614281019760e-04, + 6.57902486889110115278e-04, + 6.49397039096706574744e-04, + 6.40591855088354865909e-04, + 6.31492675367040820315e-04, + 6.22105369581239602515e-04, + 6.12435932965378496476e-04, + 6.02490482729133372541e-04, + 5.92275254397530565020e-04, + 5.81796598104019854238e-04, + 5.71060974838680235344e-04, + 5.60074952653592437156e-04, + 5.48845202827616417997e-04, + 5.37378495992671769733e-04, + 5.25681698223757196999e-04, + 5.13761767094866308656e-04, + 5.01625747702958151193e-04, + 4.89280768662212254237e-04, + 4.76734038070840296462e-04, + 4.63992839452548365767e-04, + 4.51064527674926475653e-04, + 4.37956524847056961718e-04, + 4.24676316198432479525e-04, + 4.11231445941475173573e-04, + 3.97629513119952544397e-04, + 3.83878167445365014142e-04, + 3.69985105123653247247e-04, + 3.55958064674343052560e-04, + 3.41804822744478146133e-04, + 3.27533189919382002140e-04, + 3.13151006532530441166e-04, + 2.98666138476795246359e-04, + 2.84086473019086157080e-04, + 2.69419914620704385386e-04, + 2.54674380765407412045e-04, + 2.39857797797613132851e-04, + 2.24978096772516947353e-04, + 2.10043209320515654199e-04, + 1.95061063527882452839e-04, + 1.80039579835930709352e-04, + 1.64986666960563460723e-04, + 1.49910217834334317253e-04, + 1.34818105573139893332e-04, + 1.19718179469376976285e-04, + 1.04618261013640937926e-04, + 8.95261399470057895635e-05, + 7.44495703456539838043e-05, + 5.93962667399166655609e-05, + 4.43739002695007426613e-05, + 2.93900948769175320138e-05, + 1.44524235407680616859e-05, +-4.31595449223615991972e-07, +-1.52545021735661563586e-05, +-3.00088987191676871767e-05, +-4.46874527685018162865e-05, +-5.92829011400601544354e-05, +-7.37880532784749535325e-05, +-8.81957946927382018627e-05, +-1.02499090340838023227e-04, +-1.16690987959360069175e-04, +-1.30764621336392747363e-04, +-1.44713213526426610466e-04, +-1.58530080005720515508e-04, +-1.72208631766646892702e-04, +-1.85742378349807455221e-04, +-1.99124930812504506716e-04, +-2.12350004632196330849e-04, +-2.25411422543850048289e-04, +-2.38303117309836905331e-04, +-2.51019134421297284484e-04, +-2.63553634729709143104e-04, +-2.75900897007725623075e-04, +-2.88055320438154207046e-04, +-3.00011427029988502792e-04, +-3.11763863960725555544e-04, +-3.23307405843803333592e-04, +-3.34636956920517840506e-04, +-3.45747553175349475393e-04, +-3.56634364374105745227e-04, +-3.67292696023986241921e-04, +-3.77717991254969290369e-04, +-3.87905832621729396159e-04, +-3.97851943825608877700e-04, +-4.07552191355998907722e-04, +-4.17002586050548289687e-04, +-4.26199284573830689850e-04, +-4.35138590813964924123e-04, +-4.43816957196747625784e-04, +-4.52230985917061883723e-04, +-4.60377430087148228118e-04, +-4.68253194801565195918e-04, +-4.75855338118517359660e-04, +-4.83181071957494603746e-04, +-4.90227762913035460673e-04, +-4.96992932984516386924e-04, +-5.03474260221955485957e-04, +-5.09669579287852308157e-04, +-5.15576881935093001182e-04, +-5.21194317400982664451e-04, +-5.26520192717613616691e-04, +-5.31552972938706402850e-04, +-5.36291281283125418830e-04, +-5.40733899195399727276e-04, +-5.44879766323496587781e-04, +-5.48727980414253735213e-04, +-5.52277797126791330021e-04, +-5.55528629764419335478e-04, +-5.58480048925468798571e-04, +-5.61131782073551080119e-04, +-5.63483713027851970505e-04, +-5.65535881373998238451e-04, +-5.67288481796187900146e-04, +-5.68741863331195915583e-04, +-5.69896528545036479795e-04, +-5.70753132632961161612e-04, +-5.71312482443646482352e-04, +-5.71575535428334754844e-04, +-5.71543398515829263219e-04, +-5.71217326914227299835e-04, +-5.70598722840296476537e-04, +-5.69689134177503594091e-04, +-5.68490253063648432949e-04, +-5.67003914409159020388e-04, +-5.65232094347102977452e-04, +-5.63176908616005544687e-04, +-5.60840610876602073745e-04, +-5.58225590963675973900e-04, +-5.55334373074175820066e-04, +-5.52169613892796438438e-04, +-5.48734100656311134595e-04, +-5.45030749157866334711e-04, +-5.41062601692576870642e-04, +-5.36832824945712001018e-04, +-5.32344707824832300003e-04, +-5.27601659237243400015e-04, +-5.22607205814143416754e-04, +-5.17364989582876229866e-04, +-5.11878765588764158417e-04, +-5.06152399467916375153e-04, +-5.00189864972510559588e-04, +-4.93995241450078683386e-04, +-4.87572711278240109554e-04, +-4.80926557256444178138e-04, +-4.74061159956301635728e-04, +-4.66980995031984519490e-04, +-4.59690630492344271939e-04, +-4.52194723936275402073e-04, +-4.44498019752993822097e-04, +-4.36605346288767746325e-04, +-4.28521612981757975790e-04, +-4.20251807466636860457e-04, +-4.11800992650551039072e-04, +-4.03174303762152705464e-04, +-3.94376945375264067670e-04, +-3.85414188409003615268e-04, +-3.76291367105835428391e-04, +-3.67013875989376269545e-04, +-3.57587166803538351878e-04, +-3.48016745434793248019e-04, +-3.38308168819116130647e-04, +-3.28467041835364367049e-04, +-3.18499014186804374482e-04, +-3.08409777272385283997e-04, +-2.98205061049476030047e-04, +-2.87890630889810130322e-04, +-2.77472284430191329634e-04, +-2.66955848419733049459e-04, +-2.56347175565217071970e-04, +-2.45652141376338599681e-04, +-2.34876641012365765249e-04, +-2.24026586131914569105e-04, +-2.13107901747536509227e-04, +-2.02126523086630768746e-04, +-1.91088392460356650080e-04, +-1.79999456142178738786e-04, +-1.68865661257607132476e-04, +-1.57692952686686938598e-04, +-1.46487269980864699605e-04, +-1.35254544295716316437e-04, +-1.24000695341184972607e-04, +-1.12731628350718165836e-04, +-1.01453231070878122327e-04, +-9.01713707729724520340e-05, +-7.88918912880573160781e-05, +-6.76206100668247551966e-05, +-5.63633152658752571273e-05, +-4.51257628616542845251e-05, +-3.39136737935608547517e-05, +-2.27327311375149941554e-05, +-1.15885773114489628905e-05, +-4.86811313915871210201e-07, + 1.05670140028143166991e-05, + 2.15673946238210968425e-05, + 3.25088780256781116596e-05, + 4.33860657922279085714e-05, + 5.41936161910015515536e-05, + 6.49262467088870516650e-05, + 7.55787365460706083136e-05, + 8.61459290670060090240e-05, + 9.66227342073920110596e-05, + 1.07004130835977286562e-04, + 1.17285169070277186945e-04, + 1.27460972545122102045e-04, + 1.37526740632994235337e-04, + 1.47477750615313961575e-04, + 1.57309359803685470123e-04, + 1.67017007610150564068e-04, + 1.76596217565703518526e-04, + 1.86042599286130139018e-04, + 1.95351850384440511605e-04, + 2.04519758329024586505e-04, + 2.13542202246907178919e-04, + 2.22415154671328456478e-04, + 2.31134683232958544662e-04, + 2.39696952294124378952e-04, + 2.48098224525461843754e-04, + 2.56334862424394095085e-04, + 2.64403329774836909783e-04, + 2.72300193047718441016e-04, + 2.80022122741781036813e-04, + 2.87565894664178829838e-04, + 2.94928391150552234555e-04, + 3.02106602224121655823e-04, + 3.09097626693513312206e-04, + 3.15898673188933149566e-04, + 3.22507061136495965393e-04, + 3.28920221670429965485e-04, + 3.35135698482898333403e-04, + 3.41151148611357961198e-04, + 3.46964343163231182625e-04, + 3.52573167977838467131e-04, + 3.57975624225448146778e-04, + 3.63169828943500801448e-04, + 3.68154015509882480677e-04, + 3.72926534053389822573e-04, + 3.77485851801332371845e-04, + 3.81830553364452182901e-04, + 3.85959340959241372672e-04, + 3.89871034567797159973e-04, + 3.93564572035445218046e-04, + 3.97039009106330996121e-04, + 4.00293519397200458273e-04, + 4.03327394309708944353e-04, + 4.06140042881526601437e-04, + 4.08730991576614218711e-04, + 4.11099884015009905264e-04, + 4.13246480642570374747e-04, + 4.15170658341088754176e-04, + 4.16872409979225850337e-04, + 4.18351843904797517006e-04, + 4.19609183378898695574e-04, + 4.20644765952442063056e-04, + 4.21459042785672199482e-04, + 4.22052577911266981522e-04, + 4.22426047441667507944e-04, + 4.22580238721291740270e-04, + 4.22516049424304497659e-04, + 4.22234486598678352993e-04, + 4.21736665657268593004e-04, + 4.21023809316662376602e-04, + 4.20097246484596811584e-04, + 4.18958411096749831423e-04, + 4.17608840903733937334e-04, + 4.16050176209156481050e-04, + 4.14284158559614175323e-04, + 4.12312629387525297810e-04, + 4.10137528607722027553e-04, + 4.07760893168739989995e-04, + 4.05184855559753253750e-04, + 4.02411642274163466621e-04, + 3.99443572230806823956e-04, + 3.96283055153818239771e-04, + 3.92932589912160215497e-04, + 3.89394762819913727372e-04, + 3.85672245898332176350e-04, + 3.81767795100792530199e-04, + 3.77684248501704115941e-04, + 3.73424524450519546449e-04, + 3.68991619691936916479e-04, + 3.64388607453439920380e-04, + 3.59618635501351871335e-04, + 3.54684924166520241986e-04, + 3.49590764340821041987e-04, + 3.44339515445693598438e-04, + 3.38934603373838513624e-04, + 3.33379518405329915154e-04, + 3.27677813099311473176e-04, + 3.21833100162536569697e-04, + 3.15849050295926377270e-04, + 3.09729390020389752213e-04, + 3.03477899483178554640e-04, + 2.97098410245953236785e-04, + 2.90594803055835239260e-04, + 2.83971005600701430303e-04, + 2.77230990249963083708e-04, + 2.70378771782053405493e-04, + 2.63418405099919501929e-04, + 2.56353982935728650153e-04, + 2.49189633546102382294e-04, + 2.41929518399063687127e-04, + 2.34577829853976687832e-04, + 2.27138788835770893786e-04, + 2.19616642504623810770e-04, + 2.12015661922379533436e-04, + 2.04340139716986798554e-04, + 1.96594387746109900425e-04, + 1.88782734761210285561e-04, + 1.80909524073276134666e-04, + 1.72979111221486337802e-04, + 1.64995861645938764022e-04, + 1.56964148365684399598e-04, + 1.48888349663314485498e-04, + 1.40772846777168322190e-04, + 1.32622021602487612625e-04, + 1.24440254402532454779e-04, + 1.16231921530969174315e-04, + 1.08001393166544268506e-04, + 9.97530310612700842022e-05, + 9.14911863031805467012e-05, + 8.32201970948494534723e-05, + 7.49443865486733659534e-05, + 6.66680605000458429647e-05, + 5.83955053395394390486e-05, + 5.01309858650572228258e-05, + 4.18787431550387222699e-05, + 3.36429924637896997147e-05, + 2.54279211398450498503e-05, + 1.72376865684373168860e-05, + 9.07641413898224680109e-06, + 9.48195238618905657624e-07, +-7.14291472735570851774e-06, +-1.51928982871868691030e-05, +-2.31977778255819772578e-05, +-3.11536174769894797995e-05, +-3.90565249883959565128e-05, +-4.69026535507838503733e-05, +-5.46882035983796400101e-05, +-6.24094245749816497679e-05, +-7.00626166665431140837e-05, +-7.76441324992083051551e-05, +-8.51503788021582837904e-05, +-9.25778180344744060573e-05, +-9.99229699753842974660e-05, +-1.07182413277143970569e-04, +-1.14352786980001299723e-04, +-1.21430791988570707662e-04, +-1.28413192508978856029e-04, +-1.35296817446291592216e-04, +-1.42078561761593261028e-04, +-1.48755387788243690359e-04, +-1.55324326506731677858e-04, +-1.61782478777755279195e-04, +-1.68127016532938305905e-04, +-1.74355183922886855866e-04, +-1.80464298422043775347e-04, +-1.86451751890066126042e-04, +-1.92315011589316994193e-04, +-1.98051621158110087483e-04, +-2.03659201539461954481e-04, +-2.09135451865034778822e-04, +-2.14478150293975007752e-04, +-2.19685154806484236054e-04, +-2.24754403951855035284e-04, +-2.29683917550825442361e-04, +-2.34471797352042666748e-04, +-2.39116227642561802579e-04, +-2.43615475812239792083e-04, +-2.47967892871911476695e-04, +-2.52171913925349226639e-04, +-2.56226058594915238626e-04, +-2.60128931400936235906e-04, +-2.63879222094777748236e-04, +-2.67475705945676030771e-04, +-2.70917243981398745550e-04, +-2.74202783182808239749e-04, +-2.77331356632420174182e-04, +-2.80302083617130378106e-04, +-2.83114169685247407150e-04, +-2.85766906657990832612e-04, +-2.88259672595703273380e-04, +-2.90591931718978374165e-04, +-2.92763234284938700901e-04, +-2.94773216418979381367e-04, +-2.96621599902229947550e-04, +-2.98308191915087070681e-04, +-2.99832884737117537181e-04, +-3.01195655403731915589e-04, +-3.02396565319990604306e-04, +-3.03435759831933548735e-04, +-3.04313467755884059594e-04, +-3.05030000866147890746e-04, +-3.05585753341585221812e-04, +-3.05981201171519584091e-04, +-3.06216901521509134165e-04, +-3.06293492059487573384e-04, +-3.06211690242816218007e-04, +-3.05972292566802656771e-04, +-3.05576173775270109809e-04, +-3.05024286033762090722e-04, +-3.04317658065994024481e-04, +-3.03457394254183585730e-04, +-3.02444673703895100005e-04, +-3.01280749274062569550e-04, +-2.99966946572861902810e-04, +-2.98504662920123960135e-04, +-2.96895366276984148252e-04, +-2.95140594143503544149e-04, +-2.93241952424972839204e-04, +-2.91201114267648395687e-04, +-2.89019818864694969657e-04, +-2.86699870233074851408e-04, +-2.84243135962187955679e-04, +-2.81651545935045764021e-04, +-2.78927091022785277833e-04, +-2.76071821753329086409e-04, +-2.73087846955029312987e-04, +-2.69977332376105608885e-04, +-2.66742499280753122669e-04, +-2.63385623022735818576e-04, +-2.59909031597333319095e-04, +-2.56315104172533353259e-04, +-2.52606269600299821604e-04, +-2.48785004908817504021e-04, +-2.44853833776614545140e-04, +-2.40815324989414303834e-04, +-2.36672090880646487053e-04, +-2.32426785756489917047e-04, +-2.28082104306388832628e-04, +-2.23640779999901656528e-04, +-2.19105583470820145051e-04, +-2.14479320889489653368e-04, +-2.09764832324187768019e-04, +-2.04964990092551698191e-04, +-2.00082697103893516945e-04, +-1.95120885193399471553e-04, +-1.90082513449059745374e-04, +-1.84970566532296863812e-04, +-1.79788052993171517313e-04, +-1.74538003581126675585e-04, +-1.69223469552129467206e-04, +-1.63847520973145840571e-04, +-1.58413245024881097671e-04, +-1.52923744303641519389e-04, +-1.47382135123237027838e-04, +-1.41791545817854290970e-04, +-1.36155115046730930926e-04, +-1.30475990101566258683e-04, +-1.24757325217510580588e-04, +-1.19002279888661194524e-04, +-1.13214017188868415280e-04, +-1.07395702098746854882e-04, +-1.01550499839754549119e-04, +-9.56815742161736681884e-05, +-8.97920859658150297307e-05, +-8.38851911202858713332e-05, +-7.79640393756770905178e-05, +-7.20317724744152869908e-05, +-6.60915225991128571850e-05, +-6.01464107792394842228e-05, +-5.41995453113256703899e-05, +-4.82540201935260191645e-05, +-4.23129135752554075560e-05, +-3.63792862227040107682e-05, +-3.04561800008946262114e-05, +-2.45466163730380569304e-05, +-1.86535949179281487331e-05, +-1.27800918660038342780e-05, +-6.92905865481930068159e-06, +-1.10342050454853296994e-06, + 4.69392498575835322107e-06, + 1.04601092206202085443e-05, + 1.61922939685309686330e-05, + 2.18876726998310187900e-05, + 2.75434719013333585431e-05, + 3.31569523672128619587e-05, + 3.87254104655551669952e-05, + 4.42461793799820151014e-05, + 4.97166303258813707623e-05, + 5.51341737406907975117e-05, + 6.04962604476992873623e-05, + 6.58003827929482047439e-05, + 7.10440757547033927043e-05, + 7.62249180250887078177e-05, + 8.13405330633888576592e-05, + 8.63885901206668644324e-05, + 9.13668052352641340674e-05, + 9.62729421987680101039e-05, + 1.01104813492143344174e-04, + 1.05860281191625613681e-04, + 1.10537257844079884095e-04, + 1.15133707311478630493e-04, + 1.19647645584220456037e-04, + 1.24077141563022885209e-04, + 1.28420317809117991549e-04, + 1.32675351262483061940e-04, + 1.36840473927932757339e-04, + 1.40913973528841685815e-04, + 1.44894194128284206635e-04, + 1.48779536717473748154e-04, + 1.52568459771325131390e-04, + 1.56259479770980684197e-04, + 1.59851171693240460712e-04, + 1.63342169466755023468e-04, + 1.66731166394932026195e-04, + 1.70016915545461323039e-04, + 1.73198230106457167626e-04, + 1.76273983709174160992e-04, + 1.79243110717270954634e-04, + 1.82104606482673126973e-04, + 1.84857527568029053264e-04, + 1.87500991935841927272e-04, + 1.90034179104279262861e-04, + 1.92456330269822776862e-04, + 1.94766748396794513220e-04, + 1.96964798273908584360e-04, + 1.99049906537954266611e-04, + 2.01021561664790589848e-04, + 2.02879313927801336551e-04, + 2.04622775323984274973e-04, + 2.06251619467897348657e-04, + 2.07765581453663538119e-04, + 2.09164457685255029832e-04, + 2.10448105675328230946e-04, + 2.11616443812851108683e-04, + 2.12669451099812634523e-04, + 2.13607166857295168675e-04, + 2.14429690401230681543e-04, + 2.15137180688158456340e-04, + 2.15729855931309154023e-04, + 2.16207993187385875055e-04, + 2.16571927914393662145e-04, + 2.16822053500895369719e-04, + 2.16958820767090094714e-04, + 2.16982737438119145310e-04, + 2.16894367590011544417e-04, + 2.16694331068704375103e-04, + 2.16383302882573573273e-04, + 2.15962012568937173273e-04, + 2.15431243534988864970e-04, + 2.14791832373643112571e-04, + 2.14044668154778804569e-04, + 2.13190691692375993652e-04, + 2.12230894788062836786e-04, + 2.11166319451582256295e-04, + 2.09998057098713050445e-04, + 2.08727247727178962314e-04, + 2.07355079071098812689e-04, + 2.05882785734526249080e-04, + 2.04311648304645308329e-04, + 2.02642992445200404404e-04, + 2.00878187970725529407e-04, + 1.99018647902181230460e-04, + 1.97065827504565370225e-04, + 1.95021223307131414326e-04, + 1.92886372106789062567e-04, + 1.90662849955323298245e-04, + 1.88352271131035512233e-04, + 1.85956287095443860338e-04, + 1.83476585435658924713e-04, + 1.80914888793067202884e-04, + 1.78272953778979965879e-04, + 1.75552569877858596036e-04, + 1.72755558338776385452e-04, + 1.69883771055775014205e-04, + 1.66939089437739287235e-04, + 1.63923423268464666259e-04, + 1.60838709557554023410e-04, + 1.57686911382826176059e-04, + 1.54470016724860052760e-04, + 1.51190037294350436165e-04, + 1.47849007352938516474e-04, + 1.44448982528168725411e-04, + 1.40992038623224621736e-04, + 1.37480270422103131650e-04, + 1.33915790490908510934e-04, + 1.30300727975883427756e-04, + 1.26637227398848910710e-04, + 1.22927447450726668463e-04, + 1.19173559783751544113e-04, + 1.15377747803056433318e-04, + 1.11542205458248867627e-04, + 1.07669136035655032668e-04, + 1.03760750951825973841e-04, + 9.98192685489614168559e-05, + 9.58469128929003691322e-05, + 9.18459125742597699837e-05, + 8.78184995133790156831e-05, + 8.37669077696560454268e-05, + 7.96933723559265666005e-05, + 7.56001280584259725565e-05, + 7.14894082630083944159e-05, + 6.73634437881340204573e-05, + 6.32244617252882825861e-05, + 5.90746842873461779663e-05, + 5.49163276654787824009e-05, + 5.07516008951872145687e-05, + 4.65827047319741682405e-05, + 4.24118305372229097931e-05, + 3.82411591748462793188e-05, + 3.40728599191875283292e-05, + 2.99090893747361998109e-05, + 2.57519904081409751117e-05, + 2.16036910930649429937e-05, + 1.74663036683280136440e-05, + 1.33419235098453462380e-05, + 9.23262811685928130563e-06, + 5.14047611288089638620e-06, + 1.06750626183722631479e-06, +-2.98426350016022994691e-06, +-7.01283701696614740918e-06, +-1.10162408480615069031e-05, +-1.49925251873214083662e-05, +-1.89397647644820879499e-05, +-2.28560597288927702187e-05, +-2.67395365152196406880e-05, +-3.05883486907130078530e-05, +-3.44006777836602540958e-05, +-3.81747340927275210175e-05, +-4.19087574768357373853e-05, +-4.56010181252311126428e-05, +-4.92498173074900873615e-05, +-5.28534881031252298821e-05, +-5.64103961105393312886e-05, +-5.99189401350206662131e-05, +-6.33775528555675324869e-05, +-6.67847014702764807609e-05, +-7.01388883200425772204e-05, +-7.34386514903965126506e-05, +-7.66825653912348156535e-05, +-7.98692413142890845568e-05, +-8.29973279680875074835e-05, +-8.60655119903289004060e-05, +-8.90725184374467171371e-05, +-9.20171112512619700620e-05, +-9.48980937025603441979e-05, +-9.77143088115187759442e-05, +-1.00464639744859388255e-04, +-1.03148010189625194497e-04, +-1.05763384703536859194e-04, +-1.08309769041847384465e-04, +-1.10786210460631133696e-04, +-1.13191797996501934058e-04, +-1.15525662722708351705e-04, +-1.17786977981613268270e-04, +-1.19974959593534190815e-04, +-1.22088866041986484267e-04, +-1.24127998635342794240e-04, +-1.26091701644931496271e-04, +-1.27979362419654144924e-04, +-1.29790411477168272404e-04, +-1.31524322571708625470e-04, +-1.33180612738637493483e-04, +-1.34758842315833984394e-04, +-1.36258614942015598460e-04, +-1.37679577532133398362e-04, +-1.39021420229953017716e-04, +-1.40283876337992947491e-04, +-1.41466722224963323403e-04, +-1.42569777210869091466e-04, +-1.43592903429972301504e-04, +-1.44536005671797138268e-04, +-1.45399031200369268681e-04, +-1.46181969551921958151e-04, +-1.46884852311272975705e-04, +-1.47507752867118645777e-04, +-1.48050786146473433835e-04, +-1.48514108328523704045e-04, +-1.48897916538148837292e-04, +-1.49202448519377127998e-04, +-1.49427982289073205905e-04, +-1.49574835771129388594e-04, +-1.49643366411473540236e-04, +-1.49633970774193841890e-04, +-1.49547084119100584043e-04, +-1.49383179961047775483e-04, +-1.49142769611348204603e-04, +-1.48826401701621687922e-04, +-1.48434661690425537565e-04, +-1.47968171353023028678e-04, +-1.47427588254649171362e-04, +-1.46813605207650059491e-04, +-1.46126949712865211208e-04, +-1.45368383385638768636e-04, +-1.44538701366849164877e-04, +-1.43638731719351636813e-04, +-1.42669334810229859632e-04, +-1.41631402679272359055e-04, +-1.40525858394075560832e-04, +-1.39353655392192250567e-04, +-1.38115776810750613777e-04, +-1.36813234803965936073e-04, +-1.35447069848972789655e-04, +-1.34018350040412986173e-04, +-1.32528170374222436503e-04, +-1.30977652021046207277e-04, +-1.29367941589733019114e-04, +-1.27700210381360810966e-04, +-1.25975653634228948810e-04, +-1.24195489760284478228e-04, +-1.22360959573421820921e-04, +-1.20473325510130619526e-04, +-1.18533870842929396042e-04, +-1.16543898887054415644e-04, +-1.14504732200871589131e-04, +-1.12417711780453782031e-04, +-1.10284196248804102999e-04, +-1.08105561040170155152e-04, +-1.05883197579935365976e-04, +-1.03618512460517512327e-04, +-1.01312926613771452371e-04, +-9.89678744803231588006e-05, +-9.65848031763287176834e-05, +-9.41651716580904694746e-05, +-9.17104498849975562341e-05, +-8.92221179812627604834e-05, +-8.67016653968825132086e-05, +-8.41505900682881210822e-05, +-8.15703975791493105397e-05, +-7.89626003217504745472e-05, +-7.63287166594104368560e-05, +-7.36702700903663770804e-05, +-7.09887884135877711683e-05, +-6.82858028969257033506e-05, +-6.55628474480432515319e-05, +-6.28214577885690295556e-05, +-6.00631706318681429140e-05, +-5.72895228648756703262e-05, +-5.45020507343892520119e-05, +-5.17022890382489225453e-05, +-4.88917703218011553620e-05, +-4.60720240800406300981e-05, +-4.32445759658305523042e-05, +-4.04109470046085756875e-05, +-3.75726528159311059401e-05, +-3.47312028422512456081e-05, +-3.18880995853173453093e-05, +-2.90448378505280945666e-05, +-2.62029039996194488388e-05, +-2.33637752120533564114e-05, +-2.05289187554215721418e-05, +-1.76997912652334544591e-05, +-1.48778380343994300278e-05, +-1.20644923127652564947e-05, +-9.26117461698225729130e-06, +-6.46929205104167329041e-06, +-3.69023763779291335841e-06, +-9.25389661709245930119e-07, + 1.82388897678174475935e-06, + 4.55625139514285705999e-06, + 7.27036735044587330100e-06, + 9.96492384873170706833e-06, + 1.26386257417392112551e-05, + 1.52901963107384078629e-05, + 1.79183778372582360025e-05, + 2.05219321604610694255e-05, + 2.30996412209251530034e-05, + 2.56503075906517305266e-05, + 2.81727549890619002719e-05, + 3.06658287848128515438e-05, + 3.31283964832040277388e-05, + 3.55593481990333369126e-05, + 3.79575971147140200598e-05, + 4.03220799234941648030e-05, + 4.26517572576077638367e-05, + 4.49456141012434531802e-05, + 4.72026601881682524812e-05, + 4.94219303839001843038e-05, + 5.16024850522865696258e-05, + 5.37434104064078973302e-05, + 5.58438188436953509251e-05, + 5.79028492651570688234e-05, + 5.99196673786599580684e-05, + 6.18934659861721192748e-05, + 6.38234652549182388762e-05, + 6.57089129723729151135e-05, + 6.75490847850720971908e-05, + 6.93432844211934012709e-05, + 7.10908438968675459669e-05, + 7.27911237062255626245e-05, + 7.44435129951590121491e-05, + 7.60474297187843856823e-05, + 7.76023207826402985129e-05, + 7.91076621676173416964e-05, + 8.05629590386577253093e-05, + 8.19677458372435649003e-05, + 8.33215863577352583002e-05, + 8.46240738076027652209e-05, + 8.58748308515986194002e-05, + 8.70735096399619166833e-05, + 8.82197918207153089585e-05, + 8.93133885361372406803e-05, + 9.03540404035136604684e-05, + 9.13415174802592236660e-05, + 9.22756192135239819386e-05, + 9.31561743743901176599e-05, + 9.39830409767967284683e-05, + 9.47561061813165863036e-05, + 9.54752861839191087042e-05, + 9.61405260898756268200e-05, + 9.67517997729504849579e-05, + 9.73091097200465650948e-05, + 9.78124868614685578656e-05, + 9.82619903869737118746e-05, + 9.86577075477993088205e-05, + 9.89997534448505824923e-05, + 9.92882708032377870244e-05, + 9.95234297333714079334e-05, + 9.97054274788150226867e-05, + 9.98344881511112553288e-05, + 9.99108624517949686465e-05, + 9.99348273818228400017e-05, + 9.99066859386446587009e-05, + 9.98267668011501124433e-05, + 9.96954240027345068914e-05, + 9.95130365927253445271e-05, + 9.92800082864197933671e-05, + 9.89967671039888494865e-05, + 9.86637649985053661076e-05, + 9.82814774733607114231e-05, + 9.78504031893375142773e-05, + 9.73710635616093991710e-05, + 9.68440023469432334675e-05, + 9.62697852213858742314e-05, + 9.56489993487133770321e-05, + 9.49822529399337749968e-05, + 9.42701748041285732824e-05, + 9.35134138909305995691e-05, + 9.27126388249273401896e-05, + 9.18685374322917528561e-05, + 9.09818162599413001162e-05, + 9.00532000875254733281e-05, + 8.90834314325462917842e-05, + 8.80732700489246370709e-05, + 8.70234924193121910140e-05, + 8.59348912414666484460e-05, + 8.48082749089950011304e-05, + 8.36444669867888660050e-05, + 8.24443056814470995493e-05, + 8.12086433070261377561e-05, + 7.99383457464084788138e-05, + 7.86342919086182418845e-05, + 7.72973731824044141140e-05, + 7.59284928863964466827e-05, + 7.45285657161542757073e-05, + 7.30985171884366598380e-05, + 7.16392830829906657707e-05, + 7.01518088821840928807e-05, + 6.86370492088033058069e-05, + 6.70959672623157418921e-05, + 6.55295342539230995203e-05, + 6.39387288407061954269e-05, + 6.23245365591873072856e-05, + 6.06879492586022889272e-05, + 5.90299645341966667546e-05, + 5.73515851608610711097e-05, + 5.56538185273922726215e-05, + 5.39376760716902238437e-05, + 5.22041727171985520334e-05, + 5.04543263108674547410e-05, + 4.86891570629490461476e-05, + 4.69096869889039770705e-05, + 4.51169393537250871997e-05, + 4.33119381189441731090e-05, + 4.14957073926132242688e-05, + 3.96692708825496971343e-05, + 3.78336513531005402778e-05, + 3.59898700857156045134e-05, + 3.41389463435847715115e-05, + 3.22818968406223129981e-05, + 3.04197352150379130334e-05, + 2.85534715077610400016e-05, + 2.66841116459819329256e-05, + 2.48126569320371454517e-05, + 2.29401035378939945552e-05, + 2.10674420054833346785e-05, + 1.91956567530948109463e-05, + 1.73257255880832701685e-05, + 1.54586192260933851384e-05, + 1.35953008170508304306e-05, + 1.17367254781075038266e-05, + 9.88383983376396622401e-06, + 8.03758156337068200962e-06, + 6.19887895622111748366e-06, + 4.36865047440966400299e-06, + 2.54780432366209949829e-06, + 7.37238032308926373124e-07, +-1.06216196140181903275e-06, +-2.84952071350109670505e-06, +-4.62397516982719811819e-06, +-6.38467455271440543276e-06, +-8.13078073870770317037e-06, +-9.86146862713564825958e-06, +-1.15759264994108745933e-05, +-1.32733563689023272133e-05, +-1.49529743212684799525e-05, +-1.66140108451148118640e-05, +-1.82557111528464673220e-05, +-1.98773354916211406247e-05, +-2.14781594442844695424e-05, +-2.30574742201769104257e-05, +-2.46145869357362549322e-05, +-2.61488208847895399478e-05, +-2.76595157984633117411e-05, +-2.91460280946186709296e-05, +-3.06077311167595817127e-05, +-3.20440153623401097595e-05, +-3.34542887004032530218e-05, +-3.48379765785163355760e-05, +-3.61945222189482393904e-05, +-3.75233868040389463073e-05, +-3.88240496507459911801e-05, +-4.00960083743247562354e-05, +-4.13387790411311751020e-05, +-4.25518963105175459442e-05, +-4.37349135658282231866e-05, +-4.48874030344820757594e-05, +-4.60089558971416373264e-05, +-4.70991823859845203494e-05, +-4.81577118720843649186e-05, +-4.91841929419274583989e-05, +-5.01782934630889257735e-05, +-5.11397006390924718810e-05, +-5.20681210535034743074e-05, +-5.29632807032923507936e-05, +-5.38249250215106612256e-05, +-5.46528188893461618547e-05, +-5.54467466376069967565e-05, +-5.62065120377057097340e-05, +-5.69319382822057842072e-05, +-5.76228679550160513534e-05, +-5.82791629913088267694e-05, +-5.89007046272428875285e-05, +-5.94873933395923440545e-05, +-6.00391487753712058541e-05, +-6.05559096715516123285e-05, +-6.10376337649892107507e-05, +-6.14842976926593108057e-05, +-6.18958968823238233226e-05, +-6.22724454337409338497e-05, +-6.26139759905511322129e-05, +-6.29205396029612726468e-05, +-6.31922055813587270996e-05, +-6.34290613409973911456e-05, +-6.36312122378911084342e-05, +-6.37987813960626292450e-05, +-6.39319095262928170339e-05, +-6.40307547365266211065e-05, +-6.40954923340890131856e-05, +-6.41263146198697370432e-05, +-6.41234306746411955895e-05, +-6.40870661376762528177e-05, +-6.40174629778308577552e-05, +-6.39148792572699500983e-05, +-6.37795888880064606964e-05, +-6.36118813814352140369e-05, +-6.34120615910403414867e-05, +-6.31804494484613599157e-05, +-6.29173796931019454690e-05, +-6.26232015954722085176e-05, +-6.22982786744524704445e-05, +-6.19429884086736173409e-05, +-6.15577219422070999163e-05, +-6.11428837847619450737e-05, +-6.06988915065878725514e-05, +-6.02261754282833389803e-05, +-5.97251783057105978649e-05, +-5.91963550102224186499e-05, +-5.86401722044022619997e-05, +-5.80571080135254614690e-05, +-5.74476516929463732093e-05, +-5.68123032916220525477e-05, +-5.61515733119774190850e-05, +-5.54659823663211952113e-05, +-5.47560608300273307289e-05, +-5.40223484916846797155e-05, +-5.32653942004291476500e-05, +-5.24857555106721337967e-05, +-5.16839983244288007024e-05, +-5.08606965314631670927e-05, +-5.00164316474561513313e-05, +-4.91517924504131009438e-05, +-4.82673746155130051357e-05, +-4.73637803486131881954e-05, +-4.64416180186217908985e-05, +-4.55015017889379735677e-05, +-4.45440512481755157082e-05, +-4.35698910403685871315e-05, +-4.25796504948757788397e-05, +-4.15739632561744871879e-05, +-4.05534669137558035886e-05, +-3.95188026323245935744e-05, +-3.84706147824963234157e-05, +-3.74095505721943694328e-05, +-3.63362596789495190404e-05, +-3.52513938832865674302e-05, +-3.41556067034013181253e-05, +-3.30495530313091846969e-05, +-3.19338887706706398895e-05, +-3.08092704764648499791e-05, +-2.96763549967042926164e-05, +-2.85357991163705457791e-05, +-2.73882592037593264182e-05, +-2.62343908594002619289e-05, +-2.50748485677371487745e-05, +-2.39102853517339171191e-05, +-2.27413524305865331410e-05, +-2.15686988806957918462e-05, +-2.03929713000709965051e-05, +-1.92148134763324269733e-05, +-1.80348660584579070906e-05, +-1.68537662324394557363e-05, +-1.56721474009943186837e-05, +-1.44906388674901791041e-05, +-1.33098655242168735925e-05, +-1.21304475451532646111e-05, +-1.09530000833746117339e-05, +-9.77813297322283117563e-06, +-8.60645043737828595960e-06, +-7.43855079896758336784e-06, +-6.27502619881871961423e-06, +-5.11646231799598331854e-06, +-3.96343810572348692644e-06, +-2.81652551282231002175e-06, +-1.67628923075757107106e-06, +-5.43286436407872494914e-07, + 5.81933457334323180159e-07, + 1.69882904504591760570e-06, + 2.80686716623920578712e-06, + 3.90552313671397189482e-06, + 4.99428097372263609408e-06, + 6.07263361485467176461e-06, + 7.14008313057028191911e-06, + 8.19614093029787374922e-06, + 9.24032796203801469698e-06, + 1.02721749054007427328e-05, + 1.12912223580112092028e-05, + 1.22970210152323833412e-05, + 1.32891318431440794091e-05, + 1.42671262447347562611e-05, + 1.52305862192577593330e-05, + 1.61791045147036835158e-05, + 1.71122847733627428900e-05, + 1.80297416704377348772e-05, + 1.89311010456723673200e-05, + 1.98160000279815890877e-05, + 2.06840871530521841883e-05, + 2.15350224739038173570e-05, + 2.23684776643877086669e-05, + 2.31841361156243059649e-05, + 2.39816930253700516258e-05, + 2.47608554803058473310e-05, + 2.55213425312606982502e-05, + 2.62628852613713497754e-05, + 2.69852268471835885421e-05, + 2.76881226127196124491e-05, + 2.83713400765207057253e-05, + 2.90346589916937132319e-05, + 2.96778713789779565021e-05, + 3.03007815528719345064e-05, + 3.09032061408479746811e-05, + 3.14849740956869842052e-05, + 3.20459267009823244011e-05, + 3.25859175698492306789e-05, + 3.31048126368919349237e-05, + 3.36024901434722378835e-05, + 3.40788406163417342690e-05, + 3.45337668396904437789e-05, + 3.49671838206697444440e-05, + 3.53790187484598781464e-05, + 3.57692109469451898635e-05, + 3.61377118210646532115e-05, + 3.64844847969168087159e-05, + 3.68095052556900961707e-05, + 3.71127604615011769638e-05, + 3.73942494832178994610e-05, + 3.76539831103605689643e-05, + 3.78919837631567116656e-05, + 3.81082853968511798366e-05, + 3.83029334003578804196e-05, + 3.84759844893473848450e-05, + 3.86275065938727009992e-05, + 3.87575787406301688963e-05, + 3.88662909299569613790e-05, + 3.89537440076727901374e-05, + 3.90200495318706458425e-05, + 3.90653296347647622198e-05, + 3.90897168797087779285e-05, + 3.90933541134949965766e-05, + 3.90763943140510594358e-05, + 3.90390004336481431357e-05, + 3.89813452377418961383e-05, + 3.89036111395635601957e-05, + 3.88059900305833037435e-05, + 3.86886831069694882507e-05, + 3.85519006921667821723e-05, + 3.83958620557194456086e-05, + 3.82207952284667728518e-05, + 3.80269368142381611136e-05, + 3.78145317981768458210e-05, + 3.75838333518232266695e-05, + 3.73351026350875769854e-05, + 3.70686085952445174832e-05, + 3.67846277630824283257e-05, + 3.64834440463398959695e-05, + 3.61653485205640830985e-05, + 3.58306392175243310777e-05, + 3.54796209113175163119e-05, + 3.51126049022988697399e-05, + 3.47299087989734188192e-05, + 3.43318562979863894208e-05, + 3.39187769623452468762e-05, + 3.34910059980102160423e-05, + 3.30488840289914551757e-05, + 3.25927568710847293757e-05, + 3.21229753043848019326e-05, + 3.16398948447075694127e-05, + 3.11438755140624220878e-05, + 3.06352816103032127987e-05, + 3.01144814760946232977e-05, + 2.95818472673267157311e-05, + 2.90377547211135299580e-05, + 2.84825829235031577303e-05, + 2.79167140770347614077e-05, + 2.73405332682701918481e-05, + 2.67544282354346262150e-05, + 2.61587891362891606750e-05, + 2.55540083163661297088e-05, + 2.49404800776966532080e-05, + 2.43186004481496464925e-05, + 2.36887669515123128053e-05, + 2.30513783784305334912e-05, + 2.24068345583368003357e-05, + 2.17555361324791958683e-05, + 2.10978843281734282551e-05, + 2.04342807343983282075e-05, + 1.97651270788443597626e-05, + 1.90908250065320015982e-05, + 1.84117758601161542057e-05, + 1.77283804619801040644e-05, + 1.70410388982337398535e-05, + 1.63501503047186065565e-05, + 1.56561126551311619623e-05, + 1.49593225513600180476e-05, + 1.42601750161419401356e-05, + 1.35590632881392743862e-05, + 1.28563786195291532370e-05, + 1.21525100762025804540e-05, + 1.14478443406703827613e-05, + 1.07427655177589017509e-05, + 1.00376549431903564451e-05, + 9.33289099512935430329e-06, + 8.62884890878591384318e-06, + 7.92590059414905157801e-06, + 7.22441445693406108369e-06, + 6.52475522282227181239e-06, + 5.82728376506354903543e-06, + 5.13235693551778566856e-06, + 4.44032739920081165146e-06, + 3.75154347240349402752e-06, + 3.06634896445295587704e-06, + 2.38508302317038128695e-06, + 1.70807998408878326806e-06, + 1.03566922349157826689e-06, + 3.68175015318385312927e-07, +-2.94083608003316195796e-07, +-9.50792990756428532175e-07, +-1.60164498510903015186e-06, +-2.24633707822957432882e-06, +-2.88457251529725585548e-06, +-3.51606041836507742817e-06, +-4.14051590104719538038e-06, +-4.75766017899043685381e-06, +-5.36722067610390392149e-06, +-5.96893112651196722918e-06, +-6.56253167221256118968e-06, +-7.14776895641407462845e-06, +-7.72439621252695393942e-06, +-8.29217334879925126829e-06, +-8.85086702857723481774e-06, +-9.40025074617520820593e-06, +-9.94010489835155732234e-06, +-1.04702168513777000056e-05, +-1.09903810036992033189e-05, +-1.15003988441811452764e-05, +-1.20000790059446446682e-05, +-1.24892373157938542529e-05, +-1.29676968392356399312e-05, +-1.34352879211056542826e-05, +-1.38918482218078280619e-05, +-1.43372227491767596487e-05, +-1.47712638859842104608e-05, +-1.51938314131016376365e-05, +-1.56047925283423453849e-05, +-1.60040218609994824601e-05, +-1.63914014821137958761e-05, +-1.67668209104843766012e-05, +-1.71301771144641440945e-05, +-1.74813745095637493407e-05, +-1.78203249518961361498e-05, +-1.81469477275017576168e-05, +-1.84611695375891659296e-05, +-1.87629244797279366534e-05, +-1.90521540250400636825e-05, +-1.93288069914307297748e-05, +-1.95928395129016073037e-05, +-1.98442150049985344194e-05, +-2.00829041264385711751e-05, +-2.03088847369703611226e-05, +-2.05221418515166891200e-05, +-2.07226675906578703594e-05, +-2.09104611275098419107e-05, +-2.10855286310533183536e-05, +-2.12478832059765801270e-05, +-2.13975448290907599989e-05, +-2.15345402823791832330e-05, +-2.16589030827471214040e-05, +-2.17706734085350807535e-05, +-2.18698980228635944017e-05, +-2.19566301938759495123e-05, +-2.20309296119498917597e-05, +-2.20928623039478315611e-05, +-2.21425005445764114633e-05, +-2.21799227649298888801e-05, +-2.22052134582895725366e-05, +-2.22184630832555388114e-05, +-2.22197679642845197419e-05, +-2.22092301897129874779e-05, +-2.21869575073414682510e-05, +-2.21530632176585956473e-05, +-2.21076660647849037526e-05, +-2.20508901252157237687e-05, +-2.19828646944432693725e-05, +-2.19037241715403474508e-05, +-2.18136079417860268177e-05, +-2.17126602574166129554e-05, +-2.16010301165839486721e-05, +-2.14788711406044598715e-05, +-2.13463414495824367763e-05, +-2.12036035364909901271e-05, +-2.10508241397952941727e-05, +-2.08881741147017592605e-05, +-2.07158283031179152496e-05, +-2.05339654024071466103e-05, +-2.03427678330234534560e-05, +-2.01424216051101083219e-05, +-1.99331161841466409333e-05, +-1.97150443557298639234e-05, +-1.94884020895712982066e-05, +-1.92533884027966296513e-05, +-1.90102052226298810192e-05, +-1.87590572485473988781e-05, +-1.85001518139830994003e-05, +-1.82336987476685074346e-05, +-1.79599102346913299191e-05, +-1.76790006773522863739e-05, +-1.73911865559027042601e-05, +-1.70966862892450109082e-05, +-1.67957200956739338487e-05, +-1.64885098537402634234e-05, +-1.61752789633142813903e-05, +-1.58562522069297573337e-05, +-1.55316556114829399716e-05, +-1.52017163103647922620e-05, +-1.48666624061033995360e-05, +-1.45267228335893107877e-05, +-1.41821272239584706039e-05, +-1.38331057692081632425e-05, +-1.34798890876143142534e-05, +-1.31227080900243395635e-05, +-1.27617938470932148766e-05, +-1.23973774575348411156e-05, +-1.20296899174529279452e-05, +-1.16589619908198458004e-05, +-1.12854240811699317332e-05, +-1.09093061045693789425e-05, +-1.05308373639278654549e-05, +-1.01502464247116462527e-05, +-9.76776099211927309387e-06, +-9.38360778978138410360e-06, +-8.99801244003842426661e-06, +-8.61119934585468618966e-06, +-8.22339157442569339263e-06, +-7.83481074252833694781e-06, +-7.44567690366960780872e-06, +-7.05620843708181691813e-06, +-6.66662193861726721860e-06, +-6.27713211358587016620e-06, +-5.88795167158394612084e-06, +-5.49929122336098261949e-06, +-5.11135917976332167136e-06, +-4.72436165279991700163e-06, +-4.33850235886762889933e-06, +-3.95398252417811778438e-06, +-3.57100079241896547341e-06, +-3.18975313468634483958e-06, +-2.81043276172503517281e-06, +-2.43323003850372685734e-06, +-2.05833240115816176063e-06, +-1.68592427633299744872e-06, +-1.31618700294525707091e-06, +-9.49298756398597503033e-07, +-5.85434475269598042740e-07, +-2.24765790491995588430e-07, + 1.32539042944795253329e-07, + 4.86315211761806101974e-07, + 8.36401407601896179804e-07, + 1.18263988767470755612e-06, + 1.52487653281902728484e-06, + 1.86296090296814218483e-06, + 2.19674629001149769367e-06, + 2.52608976803993208671e-06, + 2.85085224096945087408e-06, + 3.17089848753367322990e-06, + 3.48609720364736703897e-06, + 3.79632104212865399887e-06, + 4.10144664978819417086e-06, + 4.40135470188026015846e-06, + 4.69592993391712774085e-06, + 4.98506117085352237869e-06, + 5.26864135364426027284e-06, + 5.54656756317971894038e-06, + 5.81874104161062011015e-06, + 6.08506721106972112904e-06, + 6.34545568979961026893e-06, + 6.59982030570251321293e-06, + 6.84807910732276385433e-06, + 7.09015437227939167509e-06, + 7.32597261316240703008e-06, + 7.55546458091406095787e-06, + 7.77856526571271897894e-06, + 7.99521389537842829865e-06, + 8.20535393132500495055e-06, + 8.40893306208027325446e-06, + 8.60590319439752568476e-06, + 8.79622044198663719764e-06, + 8.97984511188937595011e-06, + 9.15674168852855148177e-06, + 9.32687881545792753647e-06, + 9.49022927484590670408e-06, + 9.64676996472301928230e-06, + 9.79648187402453286072e-06, + 9.93935005546419846816e-06, + 1.00753635962716102202e-05, + 1.02045155868300701406e-05, + 1.03268030872496085793e-05, + 1.04422270919149080961e-05, + 1.05507924920450241771e-05, + 1.06525080363035427313e-05, + 1.07473862895008009574e-05, + 1.08354435894281464503e-05, + 1.09167000018650293508e-05, + 1.09911792738028123146e-05, + 1.10589087849281107333e-05, + 1.11199194974072203387e-05, + 1.11742459040198995155e-05, + 1.12219259746838584705e-05, + 1.12630011014179261237e-05, + 1.12975160417893515888e-05, + 1.13255188608912239713e-05, + 1.13470608718986725231e-05, + 1.13621965752502408455e-05, + 1.13709835965033970314e-05, + 1.13734826229117897745e-05, + 1.13697573387741017237e-05, + 1.13598743596030994434e-05, + 1.13439031651642332040e-05, + 1.13219160314340630866e-05, + 1.12939879615281848059e-05, + 1.12601966156488724434e-05, + 1.12206222401028280833e-05, + 1.11753475954396282394e-05, + 1.11244578837614569632e-05, + 1.10680406752547680398e-05, + 1.10061858339946508134e-05, + 1.09389854430727538072e-05, + 1.08665337290993678862e-05, + 1.07889269861304655274e-05, + 1.07062634990703402997e-05, + 1.06186434666001975772e-05, + 1.05261689236834371503e-05, + 1.04289436636973722826e-05, + 1.03270731602417616547e-05, + 1.02206644886739122943e-05, + 1.01098262474197981978e-05, + 9.99466847911029713993e-06, + 9.87530259159213775891e-06, + 9.75184127886138886650e-06, + 9.62439844196833259673e-06, + 9.49308910994118403798e-06, + 9.35802936077670613891e-06, + 9.21933624254407122552e-06, + 9.07712769464878633412e-06, + 8.93152246930307774312e-06, + 8.78264005324776636302e-06, + 8.63060058977119588699e-06, + 8.47552480106907815021e-06, + 8.31753391098935562125e-06, + 8.15674956820603695338e-06, + 7.99329376986349665764e-06, + 7.82728878573373623468e-06, + 7.65885708292866533933e-06, + 7.48812125120667820171e-06, + 7.31520392891465129538e-06, + 7.14022772960352193400e-06, + 6.96331516935741928119e-06, + 6.78458859487234582688e-06, + 6.60417011232208535555e-06, + 6.42218151704836629878e-06, + 6.23874422410881874162e-06, + 6.05397919971873245333e-06, + 5.86800689361913014930e-06, + 5.68094717240549469965e-06, + 5.49291925384726654124e-06, + 5.30404164223008170432e-06, + 5.11443206475166292147e-06, + 4.92420740899910160668e-06, + 4.73348366153649160803e-06, + 4.54237584763147922608e-06, + 4.35099797214519011545e-06, + 4.15946296161273383862e-06, + 3.96788260753767942779e-06, + 3.77636751092580240556e-06, + 3.58502702807880729068e-06, + 3.39396921767065449759e-06, + 3.20330078912824216524e-06, + 3.01312705233424288917e-06, + 2.82355186867183291849e-06, + 2.63467760343009042062e-06, + 2.44660507958478551702e-06, + 2.25943353297212192994e-06, + 2.07326056886889636990e-06, + 1.88818211999486711094e-06, + 1.70429240594666796266e-06, + 1.52168389407997070498e-06, + 1.34044726184580192320e-06, + 1.16067136059360877587e-06, + 9.82443180850182688139e-07, + 8.05847819080474491893e-07, + 6.30968445938113515307e-07, + 4.57886276012498259056e-07, + 2.86680539075394581232e-07, + 1.17428452831952805658e-07, +-4.97948028199512061526e-08, +-2.14916110022078276637e-07, +-3.77864435677151772163e-07, +-5.38570852660314438457e-07, +-6.96968559519905157610e-07, +-8.52992898671310133264e-07, +-1.00658137308563959240e-06, +-1.15767366147595502125e-06, +-1.30621163198739205903e-06, +-1.45213935439566631263e-06, +-1.59540311081938818504e-06, +-1.73595140495523324136e-06, +-1.87373496984242769148e-06, +-2.00870677416657680066e-06, +-2.14082202711105138891e-06, +-2.27003818176825526611e-06, +-2.39631493712127321177e-06, +-2.51961423860721225935e-06, +-2.63990027727692722499e-06, +-2.75713948756333368392e-06, +-2.87130054367384340272e-06, +-2.98235435462072420536e-06, +-3.09027405790690176183e-06, +-3.19503501188302714502e-06, +-3.29661478679241666049e-06, +-3.39499315452328387347e-06, +-3.49015207708610277043e-06, +-3.58207569383478124936e-06, +-3.67075030745277205795e-06, +-3.75616436872432333914e-06, +-3.83830846011024974469e-06, +-3.91717527815298500760e-06, +-3.99275961473000555479e-06, +-4.06505833718047160103e-06, +-4.13407036732752447398e-06, +-4.19979665941946242550e-06, +-4.26224017701520252964e-06, +-4.32140586883761345266e-06, +-4.37730064362061373922e-06, +-4.42993334397458008860e-06, +-4.47931471929707665449e-06, +-4.52545739775462975901e-06, +-4.56837585736176623178e-06, +-4.60808639618528355489e-06, +-4.64460710170019533535e-06, +-4.67795781932549308073e-06, +-4.70816012016700297387e-06, +-4.73523726799615031957e-06, +-4.75921418549265574824e-06, +-4.78011741977943205404e-06, +-4.79797510727910759225e-06, +-4.81281693792077799724e-06, +-4.82467411872585649209e-06, +-4.83357933680284597292e-06, +-4.83956672177992600872e-06, +-4.84267180770512457676e-06, +-4.84293149444327853537e-06, +-4.84038400859978304718e-06, +-4.83506886400059992306e-06, +-4.82702682175797029301e-06, +-4.81629984995190550901e-06, +-4.80293108295687288677e-06, +-4.78696478044319962005e-06, +-4.76844628608297569874e-06, +-4.74742198598980721643e-06, +-4.72393926692184768618e-06, +-4.69804647427729357874e-06, +-4.66979286991168869255e-06, +-4.63922858980587374532e-06, +-4.60640460161349042157e-06, +-4.57137266211669161266e-06, +-4.53418527461856474313e-06, +-4.49489564630047438049e-06, +-4.45355764557232873177e-06, +-4.41022575944365265741e-06, +-4.36495505094285770681e-06, +-4.31780111661199634214e-06, +-4.26882004410400630158e-06, +-4.21806836990897163306e-06, +-4.16560303723581088566e-06, +-4.11148135407525745674e-06, +-4.05576095146995474136e-06, +-3.99849974201671793024e-06, +-3.93975587862589741230e-06, +-3.87958771356253902739e-06, +-3.81805375779311230168e-06, +-3.75521264066174805207e-06, +-3.69112306991899966841e-06, +-3.62584379212629908306e-06, +-3.55943355345803456996e-06, +-3.49195106092336089756e-06, +-3.42345494402936616337e-06, +-3.35400371690614687047e-06, +-3.28365574091441607464e-06, +-3.21246918775588953681e-06, +-3.14050200310536497332e-06, +-3.06781187078386562419e-06, +-2.99445617749091577548e-06, +-2.92049197811430259292e-06, +-2.84597596163407434304e-06, +-2.77096441763784568063e-06, +-2.69551320346391274513e-06, +-2.61967771198731242738e-06, +-2.54351284006417954935e-06, +-2.46707295764927670231e-06, +-2.39041187760002226610e-06, +-2.31358282618092573712e-06, +-2.23663841428083219829e-06, +-2.15963060935584024358e-06, +-2.08261070810834870857e-06, +-2.00562930991492076031e-06, +-1.92873629101175331357e-06, +-1.85198077944850633880e-06, +-1.77541113081986172875e-06, +-1.69907490478282910220e-06, +-1.62301884236816257159e-06, +-1.54728884409369261285e-06, +-1.47192994888573774293e-06, +-1.39698631381516495750e-06, +-1.32250119465412662692e-06, +-1.24851692725776004904e-06, +-1.17507490977594879706e-06, +-1.10221558569852023006e-06, +-1.02997842773779330541e-06, +-9.58401922550402422422e-07, +-8.87523556300846598974e-07, +-8.17379801068637194395e-07, +-7.48006102099267160073e-07, +-6.79436865899721901669e-07, +-6.11705449178669713405e-07, +-5.44844148629825548117e-07, +-4.78884191557767192135e-07, +-4.13855727343869051617e-07, +-3.49787819750522529807e-07, +-2.86708440059940296556e-07, +-2.24644461044386128961e-07, +-1.63621651764123018711e-07, +-1.03664673187799380991e-07, +-4.47970746308059675830e-08, + 0 /* Need a final zero coefficient */ + diff --git a/libk3b/plugin/libsamplerate/samplerate.c b/libk3b/plugin/libsamplerate/samplerate.c new file mode 100644 index 0000000..58ad40a --- /dev/null +++ b/libk3b/plugin/libsamplerate/samplerate.c @@ -0,0 +1,301 @@ +/* +** Copyright (C) 2002,2003 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "config.h" + +#include "samplerate.h" +#include "common.h" + +SRC_STATE * +src_new (int converter_type, int channels, int *error) +{ SRC_PRIVATE *psrc ; + + if (error) + *error = SRC_ERR_NO_ERROR ; + + if (channels < 1) + { if (error) + *error = SRC_ERR_BAD_CHANNEL_COUNT ; + return NULL ; + } ; + + if ((psrc = calloc (1, sizeof (*psrc))) == NULL) + { if (error) + *error = SRC_ERR_MALLOC_FAILED ; + return NULL ; + } ; + + psrc->channels = channels ; + + if (sinc_set_converter (psrc, converter_type) != SRC_ERR_NO_ERROR && + zoh_set_converter (psrc, converter_type) != SRC_ERR_NO_ERROR && + linear_set_converter (psrc, converter_type) != SRC_ERR_NO_ERROR) + { if (error) + *error = SRC_ERR_BAD_CONVERTER ; + free (psrc) ; + psrc = NULL ; + } ; + + src_reset ((SRC_STATE*) psrc) ; + + return (SRC_STATE*) psrc ; +} /* src_new */ + +SRC_STATE * +src_delete (SRC_STATE *state) +{ SRC_PRIVATE *psrc ; + + psrc = (SRC_PRIVATE*) state ; + if (psrc) + { if (psrc->private_data) + free (psrc->private_data) ; + memset (psrc, 0, sizeof (SRC_PRIVATE)) ; + free (psrc) ; + } ; + + return NULL ; +} /* src_state */ + +int +src_process (SRC_STATE *state, SRC_DATA *data) +{ SRC_PRIVATE *psrc ; + int error ; + + psrc = (SRC_PRIVATE*) state ; + + if (psrc == NULL) + return SRC_ERR_BAD_STATE ; + if (psrc->process == NULL) + return SRC_ERR_BAD_PROC_PTR ; + + /* Check for valid SRC_DATA first. */ + if (data == NULL) + return SRC_ERR_BAD_DATA ; + /* Check src_ratio is in range. */ + if (data->src_ratio < (1.0 / SRC_MAX_RATIO) || data->src_ratio > (1.0 * SRC_MAX_RATIO)) + return SRC_ERR_BAD_SRC_RATIO ; + + /* And that data_in and data_out are valid. */ + if (data->data_in == NULL || data->data_out == NULL) + return SRC_ERR_BAD_DATA_PTR ; + + if (data->data_in == NULL) + data->input_frames = 0 ; + + if (data->data_in < data->data_out) + { if (data->data_in + data->input_frames * psrc->channels > data->data_out) + { /*-printf ("data_in: %p data_out: %p\n", + data->data_in + data->input_frames * psrc->channels, data->data_out) ;-*/ + return SRC_ERR_DATA_OVERLAP ; + } ; + } + else if (data->data_out + data->output_frames * psrc->channels > data->data_in) + { /*-printf ("data_out: %p (%p) data_in: %p\n", data->data_out, + data->data_out + data->output_frames * psrc->channels, data->data_in) ;-*/ + return SRC_ERR_DATA_OVERLAP ; + } ; + + if (data->input_frames < 0) + data->input_frames = 0 ; + if (data->output_frames < 0) + data->output_frames = 0 ; + + /* Set the input and output counts to zero. */ + data->input_frames_used = 0 ; + data->output_frames_gen = 0 ; + + /* Special case for when last_ratio has not been set. */ + if (psrc->last_ratio < (1.0 / SRC_MAX_RATIO)) + psrc->last_ratio = data->src_ratio ; + + /* Now process. */ + error = psrc->process (psrc, data) ; + + return error ; +} /* src_process */ + +int +src_set_ratio (SRC_STATE *state, double new_ratio) +{ SRC_PRIVATE *psrc ; + + psrc = (SRC_PRIVATE*) state ; + + if (psrc == NULL) + return SRC_ERR_BAD_STATE ; + if (psrc->process == NULL) + return SRC_ERR_BAD_PROC_PTR ; + + psrc->last_ratio = new_ratio ; + + return SRC_ERR_NO_ERROR ; +} /* src_set_ratio */ + +int +src_reset (SRC_STATE *state) +{ SRC_PRIVATE *psrc ; + + if ((psrc = (SRC_PRIVATE*) state) == NULL) + return SRC_ERR_BAD_STATE ; + + if (psrc->reset != NULL) + psrc->reset (psrc) ; + + psrc->last_position = 0.0 ; + psrc->last_ratio = 0.0 ; + + psrc->error = SRC_ERR_NO_ERROR ; + + return SRC_ERR_NO_ERROR ; +} /* src_reset */ + +/*============================================================================== +** Control functions. +*/ + +const char * +src_get_name (int converter_type) +{ const char *desc ; + + if ((desc = sinc_get_name (converter_type)) != NULL) + return desc ; + + if ((desc = zoh_get_name (converter_type)) != NULL) + return desc ; + + if ((desc = linear_get_name (converter_type)) != NULL) + return desc ; + + return NULL ; +} /* src_get_name */ + +const char * +src_get_description (int converter_type) +{ const char *desc ; + + if ((desc = sinc_get_description (converter_type)) != NULL) + return desc ; + + if ((desc = zoh_get_description (converter_type)) != NULL) + return desc ; + + if ((desc = linear_get_description (converter_type)) != NULL) + return desc ; + + return NULL ; +} /* src_get_description */ + +const char * +src_get_version (void) +{ return "libsamplerate-k3b";/*PACKAGE "-" VERSION ;*/ +} /* src_get_version */ + +int +src_is_valid_ratio (double ratio) +{ + if (ratio < (1.0 / SRC_MAX_RATIO) || ratio > (1.0 * SRC_MAX_RATIO)) + return SRC_FALSE ; + + return SRC_TRUE ; +} /* src_is_valid_ratio */ + +/*============================================================================== +** Error reporting functions. +*/ + +int +src_error (SRC_STATE *state) +{ if (state) + return ((SRC_PRIVATE*) state)->error ; + return SRC_ERR_NO_ERROR ; +} /* src_error */ + +const char* +src_strerror (int error) +{ + switch (error) + { case SRC_ERR_NO_ERROR : + return "No error" ; + case SRC_ERR_MALLOC_FAILED : + return "Malloc failed." ; + case SRC_ERR_BAD_STATE : + return "SRC_STATE pointer is NULL." ; + case SRC_ERR_BAD_DATA : + return "SRC_DATA pointer is NULL." ; + case SRC_ERR_BAD_DATA_PTR : + return "SRC_DATA->data_out is NULL." ; + case SRC_ERR_NO_PRIVATE : + return "Internal error. No private data." ; + case SRC_ERR_BAD_SRC_RATIO : + return "SRC ratio outside [-12, 12] range." ; + case SRC_ERR_BAD_SINC_STATE : + return "src_process() called without reset after end_of_input." ; + case SRC_ERR_BAD_PROC_PTR : + return "Internal error. No process pointer." ; + case SRC_ERR_SHIFT_BITS : + return "Internal error. SHIFT_BITS too large." ; + case SRC_ERR_FILTER_LEN : + return "Internal error. Filter length too large." ; + case SRC_ERR_BAD_CONVERTER : + return "Bad converter number." ; + case SRC_ERR_BAD_CHANNEL_COUNT : + return "Channel count must be >= 1." ; + case SRC_ERR_SINC_BAD_BUFFER_LEN : + return "Internal error. Bad buffer length. Please report this." ; + case SRC_ERR_SIZE_INCOMPATIBILITY : + return "Internal error. Input data / internal buffer size difference. Please report this." ; + case SRC_ERR_BAD_PRIV_PTR : + return "Internal error. Private pointer is NULL. Please report this." ; + + case SRC_ERR_DATA_OVERLAP : + return "Input and output data arrays overlap." ; + + case SRC_ERR_MAX_ERROR : + return "Placeholder. No error defined for this error number." ; + + default : break ; + } + + return NULL ; +} /* src_strerror */ + +/*============================================================================== +** Simple interface for performing a single conversion from input buffer to +** output buffer at a fixed conversion ratio. +*/ + +int +src_simple (SRC_DATA *src_data, int converter, int channels) +{ SRC_STATE *src_state ; + int error ; + + if ((src_state = src_new (converter, channels, &error)) == NULL) + return error ; + + src_data->end_of_input = 1 ; /* Only one buffer worth of input. */ + + error = src_process (src_state, src_data) ; + + src_state = src_delete (src_state) ; + + return error ; +} /* src_simple */ + diff --git a/libk3b/plugin/libsamplerate/samplerate.h b/libk3b/plugin/libsamplerate/samplerate.h new file mode 100644 index 0000000..dfc4448 --- /dev/null +++ b/libk3b/plugin/libsamplerate/samplerate.h @@ -0,0 +1,138 @@ +/* +** Copyright (C) 2002,2003 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* +** API documentation is available here: +** http://www.mega-nerd.com/SRC/api.html +*/ + +#ifndef SAMPLERATE_H +#define SAMPLERATE_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct SRC_STATE_tag SRC_STATE ; + +typedef struct +{ float *data_in, *data_out ; + + long input_frames, output_frames ; + long input_frames_used, output_frames_gen ; + + int end_of_input ; + + double src_ratio ; +} SRC_DATA ; + +/* +** Simple interface for performing a single conversion from input buffer to +** output buffer at a fixed conversion ratio. +*/ +int src_simple (SRC_DATA *data, int converter_type, int channels) ; + +/* +** Initialisation function : return an anonymous pointer to the internal state +** of the converter. Choose a converter from the enums below. +*/ + +SRC_STATE* src_new (int converter_type, int channels, int *error) ; + +/* +** Cleanup all internal allocations. +** Always returns NULL. +*/ + +SRC_STATE* src_delete (SRC_STATE *state) ; + +/* +** This library contains a number of different sample rate converters, +** numbered 0 through N. +** +** Return a string giving either a name or a more full description of each +** sample rate converter or NULL if no sample rate converter exists for +** the given value. The converters are sequentially numbered from 0 to N. +*/ + +const char *src_get_name (int converter_type) ; +const char *src_get_description (int converter_type) ; +const char *src_get_version (void) ; + +/* +** Processing function. +** Returns non zero on error. +*/ + +int src_process (SRC_STATE *state, SRC_DATA *data) ; + +/* +** Set a new SRC ratio. This allows step responses +** in the conversion ratio. +** Returns non zero on error. +*/ + +int src_set_ratio (SRC_STATE *state, double new_ratio) ; + +/* +** Reset the internal SRC state. +** Does not modify the quality settings. +** Does not free any memory allocations. +** Returns non zero on error. +*/ + +int src_reset (SRC_STATE *state) ; + +/* +** Return TRUE if ratio is a valid conversion ratio, FALSE +** otherwise. +*/ + +int src_is_valid_ratio (double ratio) ; + +/* +** Return an error number. +*/ + +int src_error (SRC_STATE *state) ; + +/* +** Convert the error number into a string. +*/ +const char* src_strerror (int error) ; + +/* +** The following enums can be used to set the interpolator type +** using the function src_set_converter(). +*/ + +enum +{ + SRC_SINC_BEST_QUALITY = 0, + SRC_SINC_MEDIUM_QUALITY = 1, + SRC_SINC_FASTEST = 2, + SRC_ZERO_ORDER_HOLD = 3, + SRC_LINEAR = 4 +} ; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* SAMPLERATE_H */ diff --git a/libk3b/plugin/libsamplerate/src_linear.c b/libk3b/plugin/libsamplerate/src_linear.c new file mode 100644 index 0000000..c1736d2 --- /dev/null +++ b/libk3b/plugin/libsamplerate/src_linear.c @@ -0,0 +1,194 @@ +/* +** Copyright (C) 2002,2003 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "config.h" +#include "float_cast.h" +#include "common.h" + +static void linear_reset (SRC_PRIVATE *psrc) ; + +/*======================================================================================== +*/ + +#define LINEAR_MAGIC_MARKER MAKE_MAGIC('l','i','n','e','a','r') + +typedef struct +{ int linear_magic_marker ; + int channels ; + long in_count, in_used ; + long out_count, out_gen ; + float last_value [1] ; +} LINEAR_DATA ; + +/*---------------------------------------------------------------------------------------- +*/ +int +linear_process (SRC_PRIVATE *psrc, SRC_DATA *data) +{ LINEAR_DATA *linear ; + double src_ratio, input_index ; + int ch ; + + if (psrc->private_data == NULL) + return SRC_ERR_NO_PRIVATE ; + + linear = (LINEAR_DATA*) psrc->private_data ; + + linear->in_count = data->input_frames * linear->channels ; + linear->out_count = data->output_frames * linear->channels ; + linear->in_used = linear->out_gen = 0 ; + + src_ratio = psrc->last_ratio ; + input_index = psrc->last_position ; + + /* Calculate samples before first sample in input array. */ + while (input_index > 0.0 && input_index < 1.0 && linear->out_gen < linear->out_count) + { + if (linear->in_used + input_index > linear->in_count) + break ; + + if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) + src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / (linear->out_count - 1) ; + + for (ch = 0 ; ch < linear->channels ; ch++) + { data->data_out [linear->out_gen] = linear->last_value [ch] + input_index * + (data->data_in [ch] - linear->last_value [ch]) ; + linear->out_gen ++ ; + } ; + + /* Figure out the next index. */ + input_index += 1.0 / src_ratio ; + } ; + + /* Main processing loop. */ + while (linear->out_gen < linear->out_count) + { + linear->in_used += linear->channels * lrint (floor (input_index)) ; + input_index -= floor (input_index) ; + + if (linear->in_used + input_index > linear->in_count) + break ; + + if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) + src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / (linear->out_count - 1) ; + + for (ch = 0 ; ch < linear->channels ; ch++) + { data->data_out [linear->out_gen] = data->data_in [linear->in_used + ch] + input_index * + (data->data_in [linear->in_used + linear->channels + ch] - data->data_in [linear->in_used + ch]) ; + linear->out_gen ++ ; + } ; + + /* Figure out the next index. */ + input_index += 1.0 / src_ratio ; + } ; + +/*- if (input_index > linear->in_count - linear->in_used) + { input_index -= linear->in_count - linear->in_used ; + linear->in_used = linear->in_count ; + puts ("XXXXXXXXXX") ; /+*-exit (1) ;-*+/ + } ; +-*/ + + psrc->last_position = input_index ; + + for (ch = 0 ; ch < linear->channels ; ch++) + { linear->last_value [ch] = data->data_in [linear->in_used - linear->channels + ch] ; + +/*- data->data_out [0 + ch] = -0.9 ; + data->data_out [linear->out_gen - linear->channels + ch] = 0.9 ; -*/ + } ; + + /* Save current ratio rather then target ratio. */ + psrc->last_ratio = src_ratio ; + + data->input_frames_used = linear->in_used / linear->channels ; + data->output_frames_gen = linear->out_gen / linear->channels ; + + return SRC_ERR_NO_ERROR ; +} /* linear_process */ + +/*------------------------------------------------------------------------------ +*/ + +const char* +linear_get_name (int src_enum) +{ + if (src_enum == SRC_LINEAR) + return "Linear Interpolator" ; + + return NULL ; +} /* linear_get_name */ + +const char* +linear_get_description (int src_enum) +{ + if (src_enum == SRC_LINEAR) + return "Linear interpolator, very fast, poor quality." ; + + return NULL ; +} /* linear_get_descrition */ + +int +linear_set_converter (SRC_PRIVATE *psrc, int src_enum) +{ LINEAR_DATA *linear ; + + if (src_enum != SRC_LINEAR) + return SRC_ERR_BAD_CONVERTER ; + + if (psrc->private_data != NULL) + { linear = (LINEAR_DATA*) psrc->private_data ; + if (linear->linear_magic_marker != LINEAR_MAGIC_MARKER) + { free (psrc->private_data) ; + psrc->private_data = NULL ; + } ; + } ; + + if (psrc->private_data == NULL) + { linear = calloc (1, sizeof (*linear) + psrc->channels * sizeof (float)) ; + if (linear == NULL) + return SRC_ERR_MALLOC_FAILED ; + psrc->private_data = linear ; + } ; + + linear->linear_magic_marker = LINEAR_MAGIC_MARKER ; + linear->channels = psrc->channels ; + + psrc->process = linear_process ; + psrc->reset = linear_reset ; + + linear_reset (psrc) ; + + return SRC_ERR_NO_ERROR ; +} /* linear_set_converter */ + +/*=================================================================================== +*/ + +static void +linear_reset (SRC_PRIVATE *psrc) +{ LINEAR_DATA *linear ; + + linear = (LINEAR_DATA*) psrc->private_data ; + if (linear == NULL) + return ; + + memset (linear->last_value, 0, sizeof (linear->last_value [0]) * linear->channels) ; +} /* linear_reset */ diff --git a/libk3b/plugin/libsamplerate/src_sinc.c b/libk3b/plugin/libsamplerate/src_sinc.c new file mode 100644 index 0000000..ddfc06b --- /dev/null +++ b/libk3b/plugin/libsamplerate/src_sinc.c @@ -0,0 +1,471 @@ +/* +** Copyright (C) 2002,2003 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "config.h" +#include "float_cast.h" +#include "common.h" + +#define SINC_MAGIC_MARKER MAKE_MAGIC(' ','s','i','n','c',' ') + +#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0]))) + +/*======================================================================================== +** Macros for handling the index into the array for the filter. +** Double precision floating point is not accurate enough so use a 64 bit +** fixed point value instead. SHIFT_BITS (current value of 48) is the number +** of bits to the right of the decimal point. +** The rest of the macros are for retrieving the fractional and integer parts +** and for converting floats and ints to the fixed point format or from the +** fixed point type back to integers and floats. +*/ + +#define MAKE_INCREMENT_T(x) ((increment_t) (x)) + +#define SHIFT_BITS 16 +#define FP_ONE ((double) (((increment_t) 1) << SHIFT_BITS)) + +#define DOUBLE_TO_FP(x) (lrint ((x) * FP_ONE)) +#define INT_TO_FP(x) (((increment_t) (x)) << SHIFT_BITS) + +#define FP_FRACTION_PART(x) ((x) & ((((increment_t) 1) << SHIFT_BITS) - 1)) +#define FP_INTEGER_PART(x) ((x) & (((increment_t) -1) << SHIFT_BITS)) + +#define FP_TO_INT(x) (((x) >> SHIFT_BITS)) +#define FP_TO_DOUBLE(x) (FP_FRACTION_PART (x) / FP_ONE) + +/*======================================================================================== +*/ + +typedef int32_t increment_t ; +typedef float coeff_t ; + +enum +{ + STATE_BUFFER_START = 101, + STATE_DATA_CONTINUE = 102, + STATE_BUFFER_END = 103, + STATE_FINISHED +} ; + +typedef struct +{ int sinc_magic_marker ; + + int channels ; + long in_count, in_used ; + long out_count, out_gen ; + + int coeff_half_len, index_inc ; + int has_diffs ; + + double src_ratio, input_index ; + + int coeff_len ; + coeff_t const *coeffs ; + + int b_current, b_end, b_real_end, b_len ; + float *pdata ; + float buffer [1] ; +} SINC_FILTER ; + +static double calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch) ; + +static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ; + +static void sinc_reset (SRC_PRIVATE *psrc) ; + +static coeff_t const high_qual_coeffs [] = +{ +#include "high_qual_coeffs.h" +} ; /* high_qual_coeffs */ + +static coeff_t const mid_qual_coeffs [] = +{ +#include "mid_qual_coeffs.h" +} ; /* mid_qual_coeffs */ + +static coeff_t const fastest_coeffs [] = +{ +#include "fastest_coeffs.h" +} ; /* fastest_coeffs */ + +/*---------------------------------------------------------------------------------------- +*/ + +const char* +sinc_get_name (int src_enum) +{ + switch (src_enum) + { case SRC_SINC_BEST_QUALITY : + return "Best Sinc Interpolator" ; + + case SRC_SINC_MEDIUM_QUALITY : + return "Medium Sinc Interpolator" ; + + case SRC_SINC_FASTEST : + return "Fastest Sinc Interpolator" ; + } ; + + return NULL ; +} /* sinc_get_descrition */ + +const char* +sinc_get_description (int src_enum) +{ + switch (src_enum) + { case SRC_SINC_BEST_QUALITY : + return "Band limitied sinc interpolation, best quality, 97dB SNR, 96% BW." ; + + case SRC_SINC_MEDIUM_QUALITY : + return "Band limitied sinc interpolation, medium quality, 97dB SNR, 90% BW." ; + + case SRC_SINC_FASTEST : + return "Band limitied sinc interpolation, fastest, 97dB SNR, 80% BW." ; + } ; + + return NULL ; +} /* sinc_get_descrition */ + +int +sinc_set_converter (SRC_PRIVATE *psrc, int src_enum) +{ SINC_FILTER *filter, temp_filter ; + int count ; + + /* Quick sanity check. */ + if (SHIFT_BITS >= sizeof (increment_t) * 8 - 1) + return SRC_ERR_SHIFT_BITS ; + + if (psrc->private_data != NULL) + { filter = (SINC_FILTER*) psrc->private_data ; + if (filter->sinc_magic_marker != SINC_MAGIC_MARKER) + { free (psrc->private_data) ; + psrc->private_data = NULL ; + } ; + } ; + + memset (&temp_filter, 0, sizeof (temp_filter)) ; + + temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ; + temp_filter.channels = psrc->channels ; + + psrc->process = sinc_process ; + psrc->reset = sinc_reset ; + + switch (src_enum) + { case SRC_SINC_BEST_QUALITY : + temp_filter.coeffs = high_qual_coeffs ; + temp_filter.coeff_half_len = (sizeof (high_qual_coeffs) / sizeof (coeff_t)) - 1 ; + temp_filter.index_inc = 128 ; + temp_filter.has_diffs = SRC_FALSE ; + temp_filter.coeff_len = sizeof (high_qual_coeffs) / sizeof (coeff_t) ; + break ; + + case SRC_SINC_MEDIUM_QUALITY : + temp_filter.coeffs = mid_qual_coeffs ; + temp_filter.coeff_half_len = (sizeof (mid_qual_coeffs) / sizeof (coeff_t)) - 1 ; + temp_filter.index_inc = 128 ; + temp_filter.has_diffs = SRC_FALSE ; + temp_filter.coeff_len = sizeof (mid_qual_coeffs) / sizeof (coeff_t) ; + break ; + + case SRC_SINC_FASTEST : + temp_filter.coeffs = fastest_coeffs ; + temp_filter.coeff_half_len = (sizeof (fastest_coeffs) / sizeof (coeff_t)) - 1 ; + temp_filter.index_inc = 128 ; + temp_filter.has_diffs = SRC_FALSE ; + temp_filter.coeff_len = sizeof (fastest_coeffs) / sizeof (coeff_t) ; + break ; + + default : + return SRC_ERR_BAD_CONVERTER ; + } ; + + /* + ** FIXME : This needs to be looked at more closely to see if there is + ** a better way. Need to look at prepare_data () at the same time. + */ + + temp_filter.b_len = 1000 + 2 * lrint (ceil (temp_filter.coeff_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO)) ; + temp_filter.b_len *= temp_filter.channels ; + + if ((filter = calloc (1, sizeof (SINC_FILTER) + sizeof (filter->buffer [0]) * (temp_filter.b_len + temp_filter.channels))) == NULL) + return SRC_ERR_MALLOC_FAILED ; + + *filter = temp_filter ; + memset (&temp_filter, 0xEE, sizeof (temp_filter)) ; + + psrc->private_data = filter ; + + sinc_reset (psrc) ; + + count = (filter->coeff_half_len * INT_TO_FP (1)) / FP_ONE ; + + if (abs (count - filter->coeff_half_len) >= 1) + return SRC_ERR_FILTER_LEN ; + + return SRC_ERR_NO_ERROR ; +} /* sinc_set_converter */ + +static void +sinc_reset (SRC_PRIVATE *psrc) +{ SINC_FILTER *filter ; + + filter = (SINC_FILTER*) psrc->private_data ; + if (filter == NULL) + return ; + + filter->b_current = filter->b_end = 0 ; + filter->b_real_end = -1 ; + + filter->src_ratio = filter->input_index = 0.0 ; + + memset (filter->buffer, 0, filter->b_len * sizeof (filter->buffer [0])) ; + + /* Set this for a sanity check */ + memset (filter->buffer + filter->b_len, 0xAA, filter->channels * sizeof (filter->buffer [0])) ; +} /* sinc_reset */ + +/*======================================================================================== +** Beware all ye who dare pass this point. There be dragons here. +*/ + +int +sinc_process (SRC_PRIVATE *psrc, SRC_DATA *data) +{ SINC_FILTER *filter ; + double input_index, src_ratio, count, float_increment, terminate ; + increment_t increment, start_filter_index ; + int half_filter_chan_len, samples_in_hand, ch ; + + if (psrc->private_data == NULL) + return SRC_ERR_NO_PRIVATE ; + + filter = (SINC_FILTER*) psrc->private_data ; + + /* If there is not a problem, this will be optimised out. */ + if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0])) + return SRC_ERR_SIZE_INCOMPATIBILITY ; + + filter->in_count = data->input_frames * filter->channels ; + filter->out_count = data->output_frames * filter->channels ; + filter->in_used = filter->out_gen = 0 ; + + src_ratio = psrc->last_ratio ; + + /* Check the sample rate ratio wrt the buffer len. */ + count = (filter->coeff_half_len + 2.0) / filter->index_inc ; + if (MIN (psrc->last_ratio, data->src_ratio) < 1.0) + count /= MIN (psrc->last_ratio, data->src_ratio) ; + count = lrint (ceil (count)) ; + + /* Maximum coefficientson either side of center point. */ + half_filter_chan_len = filter->channels * (lrint (count) + 1) ; + + input_index = psrc->last_position ; + if (input_index >= 1.0) + { filter->b_current = (filter->b_current + filter->channels * lrint (floor (input_index))) % filter->b_len ; + input_index -= floor (input_index) ; + } ; + + float_increment = filter->index_inc ; + + filter->b_current = (filter->b_current + filter->channels * lrint (floor (input_index))) % filter->b_len ; + input_index -= floor (input_index) ; + + terminate = 1.0 / src_ratio + 1e-20 ; + + /* Main processing loop. */ + while (filter->out_gen < filter->out_count) + { + /* Need to reload buffer? */ + samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; + + if (samples_in_hand <= half_filter_chan_len) + { prepare_data (filter, data, half_filter_chan_len) ; + + samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; + if (samples_in_hand <= half_filter_chan_len) + break ; + } ; + + /* This is the termination condition. */ + if (filter->b_real_end >= 0) + { if (filter->b_current + input_index + terminate >= filter->b_real_end) + break ; + } ; + + if (fabs (psrc->last_ratio - data->src_ratio) > 1e-10) + src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / (filter->out_count - 1) ; + + float_increment = filter->index_inc * 1.0 ; + if (src_ratio < 1.0) + float_increment = filter->index_inc * src_ratio ; + + increment = DOUBLE_TO_FP (float_increment) ; + + start_filter_index = DOUBLE_TO_FP (input_index * float_increment) ; + + for (ch = 0 ; ch < filter->channels ; ch++) + { data->data_out [filter->out_gen] = (float_increment / filter->index_inc) * + calc_output (filter, increment, start_filter_index, ch) ; + filter->out_gen ++ ; + } ; + + /* Figure out the next index. */ + input_index += 1.0 / src_ratio ; + + filter->b_current = (filter->b_current + filter->channels * lrint (floor (input_index))) % filter->b_len ; + input_index -= floor (input_index) ; + } ; + + psrc->last_position = input_index ; + + /* Save current ratio rather then target ratio. */ + psrc->last_ratio = src_ratio ; + + data->input_frames_used = filter->in_used / filter->channels ; + data->output_frames_gen = filter->out_gen / filter->channels ; + + return SRC_ERR_NO_ERROR ; +} /* sinc_process */ + +/*---------------------------------------------------------------------------------------- +*/ + +static void +prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) +{ int len = 0 ; + + if (filter->b_real_end >= 0) + return ; /* This doesn't make sense, so return. */ + + if (filter->b_current == 0) + { /* Initial state. Set up zeros at the start of the buffer and + ** then load new data after that. + */ + len = filter->b_len - 2 * half_filter_chan_len ; + + filter->b_current = filter->b_end = half_filter_chan_len ; + } + else if (filter->b_end + half_filter_chan_len + filter->channels < filter->b_len) + { /* Load data at current end position. */ + len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ; + } + else + { /* Move data at end of buffer back to the start of the buffer. */ + len = filter->b_end - filter->b_current ; + memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len, + (half_filter_chan_len + len) * sizeof (filter->buffer [0])) ; + + filter->b_current = half_filter_chan_len ; + filter->b_end = filter->b_current + len ; + + /* Now load data at current end of buffer. */ + len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ; + } ; + + len = MIN (filter->in_count - filter->in_used, len) ; + len -= (len % filter->channels) ; + + memcpy (filter->buffer + filter->b_end, data->data_in + filter->in_used, + len * sizeof (filter->buffer [0])) ; + + filter->b_end += len ; + filter->in_used += len ; + + if (filter->in_used == filter->in_count && + filter->b_end - filter->b_current < 2 * half_filter_chan_len && data->end_of_input) + { /* Handle the case where all data in the current buffer has been + ** consumed and this is the last buffer. + */ + + if (filter->b_len - filter->b_end < half_filter_chan_len + 5) + { /* If necessary, move data down to the start of the buffer. */ + len = filter->b_end - filter->b_current ; + memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len, + (half_filter_chan_len + len) * sizeof (filter->buffer [0])) ; + + filter->b_current = half_filter_chan_len ; + filter->b_end = filter->b_current + len ; + } ; + + filter->b_real_end = filter->b_end ; + len = half_filter_chan_len + 5 ; + + memset (filter->buffer + filter->b_end, 0, len * sizeof (filter->buffer [0])) ; + filter->b_end += len ; + } ; + + return ; +} /* prepare_data */ + + +static double +calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch) +{ double fraction, left, right, icoeff ; + increment_t filter_index, max_filter_index ; + int data_index, coeff_count, indx ; + + /* Convert input parameters into fixed point. */ + max_filter_index = INT_TO_FP (filter->coeff_half_len) ; + + /* First apply the left half of the filter. */ + filter_index = start_filter_index ; + coeff_count = (max_filter_index - filter_index) / increment ; + filter_index = filter_index + coeff_count * increment ; + data_index = filter->b_current - filter->channels * coeff_count ; + + left = 0.0 ; + do + { fraction = FP_TO_DOUBLE (filter_index) ; + indx = FP_TO_INT (filter_index) ; + + icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; + + left += icoeff * filter->buffer [data_index + ch] ; + + filter_index -= increment ; + data_index = data_index + filter->channels ; + } + while (filter_index >= MAKE_INCREMENT_T (0)) ; + + /* Now apply the right half of the filter. */ + filter_index = increment - start_filter_index ; + coeff_count = (max_filter_index - filter_index) / increment ; + filter_index = filter_index + coeff_count * increment ; + data_index = filter->b_current + filter->channels * (1 + coeff_count) ; + + right = 0.0 ; + do + { fraction = FP_TO_DOUBLE (filter_index) ; + indx = FP_TO_INT (filter_index) ; + + icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; + + right += icoeff * filter->buffer [data_index + ch] ; + + filter_index -= increment ; + data_index = data_index - filter->channels ; + } + while (filter_index > MAKE_INCREMENT_T (0)) ; + + return (left + right) ; +} /* calc_output */ + diff --git a/libk3b/plugin/libsamplerate/src_zoh.c b/libk3b/plugin/libsamplerate/src_zoh.c new file mode 100644 index 0000000..7e18d87 --- /dev/null +++ b/libk3b/plugin/libsamplerate/src_zoh.c @@ -0,0 +1,186 @@ +/* +** Copyright (C) 2002,2003 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "config.h" +#include "float_cast.h" +#include "common.h" + +static void zoh_reset (SRC_PRIVATE *psrc) ; + +/*======================================================================================== +*/ + +#define ZOH_MAGIC_MARKER MAKE_MAGIC('s','r','c','z','o','h') + +typedef struct +{ int zoh_magic_marker ; + int channels ; + long in_count, in_used ; + long out_count, out_gen ; + float last_value [1] ; +} ZOH_DATA ; + +/*---------------------------------------------------------------------------------------- +*/ + +int +zoh_process (SRC_PRIVATE *psrc, SRC_DATA *data) +{ ZOH_DATA *zoh ; + double src_ratio, input_index ; + int ch ; + + if (psrc->private_data == NULL) + return SRC_ERR_NO_PRIVATE ; + + zoh = (ZOH_DATA*) psrc->private_data ; + + zoh->in_count = data->input_frames * zoh->channels ; + zoh->out_count = data->output_frames * zoh->channels ; + zoh->in_used = zoh->out_gen = 0 ; + + src_ratio = psrc->last_ratio ; + input_index = psrc->last_position ; + + /* Calculate samples before first sample in input array. */ + while (input_index > 0.0 && input_index < 1.0 && zoh->out_gen < zoh->out_count) + { + if (zoh->in_used + input_index >= zoh->in_count) + break ; + + if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) + src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / (zoh->out_count - 1) ; + + for (ch = 0 ; ch < zoh->channels ; ch++) + { data->data_out [zoh->out_gen] = zoh->last_value [ch] ; + zoh->out_gen ++ ; + } ; + + /* Figure out the next index. */ + input_index += 1.0 / src_ratio ; + } ; + + zoh->in_used += zoh->channels * lrint (floor (input_index)) ; + input_index -= floor (input_index) ; + + /* Main processing loop. */ + while (zoh->out_gen < zoh->out_count && zoh->in_used + input_index < zoh->in_count) + { + if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) + src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / (zoh->out_count - 1) ; + + for (ch = 0 ; ch < zoh->channels ; ch++) + { data->data_out [zoh->out_gen] = data->data_in [zoh->in_used + ch] ; + zoh->out_gen ++ ; + } ; + + /* Figure out the next index. */ + input_index += 1.0 / src_ratio ; + + zoh->in_used += zoh->channels * lrint (floor (input_index)) ; + input_index -= floor (input_index) ; + } ; + + psrc->last_position = input_index ; + + if (zoh->in_used > 0) + for (ch = 0 ; ch < zoh->channels ; ch++) + zoh->last_value [ch] = data->data_in [zoh->in_used - zoh->channels + ch] ; + + /* Save current ratio rather then target ratio. */ + psrc->last_ratio = src_ratio ; + + data->input_frames_used = zoh->in_used / zoh->channels ; + data->output_frames_gen = zoh->out_gen / zoh->channels ; + + return SRC_ERR_NO_ERROR ; +} /* zoh_process */ + +/*------------------------------------------------------------------------------ +*/ + +const char* +zoh_get_name (int src_enum) +{ + if (src_enum == SRC_ZERO_ORDER_HOLD) + return "ZOH Interpolator" ; + + return NULL ; +} /* zoh_get_name */ + +const char* +zoh_get_description (int src_enum) +{ + if (src_enum == SRC_ZERO_ORDER_HOLD) + return "Zero order hold interpolator, very fast, poor quality." ; + + return NULL ; +} /* zoh_get_descrition */ + +int +zoh_set_converter (SRC_PRIVATE *psrc, int src_enum) +{ ZOH_DATA *zoh = NULL; + + if (src_enum != SRC_ZERO_ORDER_HOLD) + return SRC_ERR_BAD_CONVERTER ; + + if (psrc->private_data != NULL) + { zoh = (ZOH_DATA*) psrc->private_data ; + if (zoh->zoh_magic_marker != ZOH_MAGIC_MARKER) + { free (psrc->private_data) ; + psrc->private_data = NULL ; + } ; + } ; + + if (psrc->private_data == NULL) + { zoh = calloc (1, sizeof (*zoh) + psrc->channels * sizeof (float)) ; + if (zoh == NULL) + return SRC_ERR_MALLOC_FAILED ; + psrc->private_data = zoh ; + } ; + + zoh->zoh_magic_marker = ZOH_MAGIC_MARKER ; + zoh->channels = psrc->channels ; + + psrc->process = zoh_process ; + psrc->reset = zoh_reset ; + + zoh_reset (psrc) ; + + return SRC_ERR_NO_ERROR ; +} /* zoh_set_converter */ + +/*=================================================================================== +*/ + +static void +zoh_reset (SRC_PRIVATE *psrc) +{ ZOH_DATA *zoh ; + + zoh = (ZOH_DATA*) psrc->private_data ; + if (zoh == NULL) + return ; + + zoh->channels = psrc->channels ; + memset (zoh->last_value, 0, sizeof (zoh->last_value [0]) * zoh->channels) ; + + return ; +} /* zoh_reset */ diff --git a/libk3b/projects/Makefile.am b/libk3b/projects/Makefile.am new file mode 100644 index 0000000..1a07372 --- /dev/null +++ b/libk3b/projects/Makefile.am @@ -0,0 +1,32 @@ +AM_CPPFLAGS= -I$(srcdir)/../../src -I$(srcdir)/../core -I$(srcdir)/../plugin -I$(srcdir)/../../libk3bdevice -I$(srcdir)/../tools -I$(srcdir)/datacd -I$(srcdir)/audiocd -I$(srcdir)/mixedcd -I$(srcdir)/movixcd -I$(srcdir)/movixdvd -I$(srcdir)/datadvd -I$(srcdir)/videocd -I$(srcdir)/videodvd $(all_includes) + +noinst_LTLIBRARIES = libk3bproject.la + +libk3bproject_la_LIBADD = ./datacd/libdata.la ./datadvd/libdvd.la ./mixedcd/libmixed.la ./videocd/libvcd.la ./videodvd/libvideodvd.la ./movixcd/libmovix.la ./movixdvd/libmovixdvd.la ./audiocd/libaudio.la + +libk3bproject_la_LDFLAGS = $(all_libraries) + +libk3bproject_la_SOURCES = k3babstractwriter.cpp \ + k3bgrowisofswriter.cpp \ + k3bgrowisofshandler.cpp \ + k3bdoc.cpp \ + k3bcdrdaowriter.cpp \ + k3bcdrecordwriter.cpp \ + k3binffilewriter.cpp \ + k3btocfilewriter.cpp \ + k3bimagefilereader.cpp \ + k3bcuefileparser.cpp \ + k3bpipebuffer.cpp + +include_HEADERS = k3bdoc.h \ + k3bgrowisofswriter.h \ + k3bcdrdaowriter.h \ + k3bcdrecordwriter.h \ + k3binffilewriter.h \ + k3btocfilewriter.h \ + k3bcuefileparser.h \ + k3bimagefilereader.h + +SUBDIRS = datacd audiocd mixedcd movixcd videocd datadvd movixdvd videodvd + +METASOURCES = AUTO diff --git a/libk3b/projects/audiocd/Makefile.am b/libk3b/projects/audiocd/Makefile.am new file mode 100644 index 0000000..60942cc --- /dev/null +++ b/libk3b/projects/audiocd/Makefile.am @@ -0,0 +1,35 @@ +AM_CPPFLAGS= -I$(srcdir)/../../../src \ + -I$(srcdir)/.. \ + -I$(srcdir)/../../core \ + -I$(srcdir)/../../plugin \ + -I$(srcdir)/../../cddb \ + -I$(srcdir)/../../../libk3bdevice \ + -I$(srcdir)/../../tools $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libaudio.la + +libaudio_la_SOURCES = k3baudiojob.cpp \ + k3baudiotrack.cpp \ + k3baudiodoc.cpp \ + k3baudiofile.cpp \ + k3baudiozerodata.cpp \ + k3baudiodatasource.cpp \ + k3baudionormalizejob.cpp \ + k3baudiojobtempdata.cpp \ + k3baudioimager.cpp \ + k3baudiomaxspeedjob.cpp \ + k3baudiocdtracksource.cpp \ + k3baudiocdtrackdrag.cpp \ + k3baudiodatasourceiterator.cpp + +include_HEADERS = k3baudiodoc.h \ + k3baudiojob.h \ + k3baudiocdtrackdrag.h \ + k3baudiotrack.h \ + k3baudiodatasource.h \ + k3baudiofile.h \ + k3baudiozerodata.h \ + k3baudiocdtracksource.h \ + k3baudiodatasourceiterator.h diff --git a/libk3b/projects/audiocd/k3baudiocdtrackdrag.cpp b/libk3b/projects/audiocd/k3baudiocdtrackdrag.cpp new file mode 100644 index 0000000..8429f25 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiocdtrackdrag.cpp @@ -0,0 +1,109 @@ +/* + * + * $Id: k3baudiocdtrackdrag.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudiocdtrackdrag.h" + +#include +#include +#include +#include +#include + +#include +#include + + +// FIXME: multiple tracks +K3bAudioCdTrackDrag::K3bAudioCdTrackDrag( const K3bDevice::Toc& toc, const QValueList& cdTrackNumbers, + const K3bCddbResultEntry& cddb, + K3bDevice::Device* lastDev, QWidget* dragSource, const char* name ) + : QStoredDrag( "k3b/audio_track_drag", dragSource, name ), + m_toc(toc), + m_cdTrackNumbers(cdTrackNumbers), + m_cddb(cddb), + m_device(lastDev) +{ + QByteArray data; + QDataStream s( data, IO_WriteOnly ); + s << (unsigned int)toc.count(); + for( K3bDevice::Toc::const_iterator it = toc.begin(); it != toc.end(); ++it ) { + const K3bDevice::Track& track = *it; + s << track.firstSector().lba() << track.lastSector().lba(); + } + QTextStream t( s.device() ); + t << cddb.cdArtist << endl + << cddb.cdTitle << endl; + for( unsigned int i = 0; i < toc.count(); ++i ) { + t << cddb.artists[i] << endl + << cddb.titles[i] << endl; + } + + s << (unsigned int)cdTrackNumbers.count(); + + for( QValueList::const_iterator it = cdTrackNumbers.begin(); + it != cdTrackNumbers.end(); ++it ) + s << *it; + + if( lastDev ) + t << lastDev->blockDeviceName() << endl; + else + t << endl; + + // TODO: the rest + setEncodedData( data ); +} + + +bool K3bAudioCdTrackDrag::decode( const QMimeSource* e, + K3bDevice::Toc& toc, QValueList& trackNumbers, + K3bCddbResultEntry& cddb, K3bDevice::Device** dev ) +{ + QByteArray data = e->encodedData( "k3b/audio_track_drag" ); + + QDataStream s( data, IO_ReadOnly ); + + unsigned int trackCnt; + s >> trackCnt; + for( unsigned int i = 0; i < trackCnt; ++i ) { + int fs, ls; + s >> fs; + s >> ls; + toc.append( K3bDevice::Track( fs, ls, K3bDevice::Track::AUDIO ) ); + } + + QTextStream t( s.device() ); + cddb.artists.clear(); + cddb.titles.clear(); + cddb.cdArtist = t.readLine(); + cddb.cdTitle = t.readLine(); + for( unsigned int i = 0; i < trackCnt; ++i ) { + cddb.artists.append( t.readLine() ); + cddb.titles.append( t.readLine() ); + } + + s >> trackCnt; + trackNumbers.clear(); + for( unsigned int i = 0; i < trackCnt; ++i ) { + int trackNumber = 0; + s >> trackNumber; + trackNumbers.append( trackNumber ); + } + + QString devName = t.readLine(); + if( dev && !devName.isEmpty() ) + *dev = k3bcore->deviceManager()->findDevice( devName ); + + return true; +} diff --git a/libk3b/projects/audiocd/k3baudiocdtrackdrag.h b/libk3b/projects/audiocd/k3baudiocdtrackdrag.h new file mode 100644 index 0000000..3148466 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiocdtrackdrag.h @@ -0,0 +1,50 @@ +/* + * + * $Id: k3baudiocdtrackdrag.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_CDTRACK_DRAG_H_ +#define _K3B_AUDIO_CDTRACK_DRAG_H_ + +#include +#include +#include + +#include +#include +#include +#include "k3b_export.h" + +class LIBK3B_EXPORT K3bAudioCdTrackDrag : public QStoredDrag +{ + public: + K3bAudioCdTrackDrag( const K3bDevice::Toc& toc, const QValueList& cdTrackNumbers, const K3bCddbResultEntry& cddb, + K3bDevice::Device* lastDev = 0, QWidget* dragSource = 0, const char* name = 0 ); + + const K3bDevice::Toc& toc() const { return m_toc; } + const QValueList& cdTrackNumbers() const { return m_cdTrackNumbers; } + const K3bCddbResultEntry& cddbEntry() const { return m_cddb; } + + bool provides( const char* mimetype ) const { return !qstrcmp( mimetype, "k3b/audio_track_drag" ); } + + static bool canDecode( const QMimeSource* s ) { return s->provides( "k3b/audio_track_drag" ); } + static bool decode( const QMimeSource* s, K3bDevice::Toc&, QValueList& trackNumbers, K3bCddbResultEntry&, K3bDevice::Device** dev = 0 ); + + private: + K3bDevice::Toc m_toc; + QValueList m_cdTrackNumbers; + K3bCddbResultEntry m_cddb; + K3bDevice::Device* m_device; +}; + +#endif diff --git a/libk3b/projects/audiocd/k3baudiocdtracksource.cpp b/libk3b/projects/audiocd/k3baudiocdtracksource.cpp new file mode 100644 index 0000000..b61e865 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiocdtracksource.cpp @@ -0,0 +1,262 @@ +/* + * + * $Id: k3baudiocdtracksource.cpp 676194 2007-06-16 08:59:19Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudiocdtracksource.h" +#include "k3baudiotrack.h" +#include "k3baudiodoc.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +K3bAudioCdTrackSource::K3bAudioCdTrackSource( const K3bDevice::Toc& toc, int cdTrackNumber, + const K3bCddbResultEntry& cddb, K3bDevice::Device* dev ) + : K3bAudioDataSource(), + m_discId( toc.discId() ), + m_length( toc[cdTrackNumber-1].length() ), + m_toc( toc ), + m_cdTrackNumber( cdTrackNumber ), + m_cddbEntry( cddb ), + m_lastUsedDevice( dev ), + m_cdParanoiaLib( 0 ), + m_initialized( false ) +{ +} + + +K3bAudioCdTrackSource::K3bAudioCdTrackSource( unsigned int discid, const K3b::Msf& length, int cdTrackNumber, + const QString& artist, const QString& title, + const QString& cdArtist, const QString& cdTitle ) + : K3bAudioDataSource(), + m_discId( discid ), + m_length( length ), + m_cdTrackNumber( cdTrackNumber ), + m_lastUsedDevice( 0 ), + m_cdParanoiaLib( 0 ), + m_initialized( false ) +{ + for( int i = 1; i < cdTrackNumber; ++i ) { + m_cddbEntry.titles.append( QString::null ); + m_cddbEntry.artists.append( QString::null ); + } + m_cddbEntry.titles.append( title ); + m_cddbEntry.artists.append( artist ); + m_cddbEntry.cdTitle = cdTitle; + m_cddbEntry.cdArtist = cdArtist; +} + + +K3bAudioCdTrackSource::K3bAudioCdTrackSource( const K3bAudioCdTrackSource& source ) + : K3bAudioDataSource( source ), + m_discId( source.m_discId ), + m_toc( source.m_toc ), + m_cdTrackNumber( source.m_cdTrackNumber ), + m_cddbEntry( source.m_cddbEntry ), + m_lastUsedDevice( source.m_lastUsedDevice ), + m_cdParanoiaLib( 0 ), + m_initialized( false ) +{ +} + + +K3bAudioCdTrackSource::~K3bAudioCdTrackSource() +{ + closeParanoia(); + delete m_cdParanoiaLib; +} + + +bool K3bAudioCdTrackSource::initParanoia() +{ + if( !m_initialized ) { + if( !m_cdParanoiaLib ) + m_cdParanoiaLib = K3bCdparanoiaLib::create(); + + if( m_cdParanoiaLib ) { + m_lastUsedDevice = searchForAudioCD(); + + // ask here for the cd since searchForAudioCD() may also be called from outside + if( !m_lastUsedDevice ) { + // could not find the CD, so ask for it + QString s = i18n("Please insert Audio CD %1%2") + .arg(m_discId, 0, 16) + .arg(m_cddbEntry.cdTitle.isEmpty() || m_cddbEntry.cdArtist.isEmpty() + ? QString::null + : " (" + m_cddbEntry.cdArtist + " - " + m_cddbEntry.cdTitle + ")"); + + while( K3bDevice::Device* dev = K3bThreadWidget::selectDevice( track()->doc()->view(), s ) ) { + if( searchForAudioCD( dev ) ) { + m_lastUsedDevice = dev; + break; + } + } + } + + // user canceled + if( !m_lastUsedDevice ) + return false; + + k3bcore->blockDevice( m_lastUsedDevice ); + + if( m_toc.isEmpty() ) + m_toc = m_lastUsedDevice->readToc(); + + if( !m_cdParanoiaLib->initParanoia( m_lastUsedDevice, m_toc ) ) { + k3bcore->unblockDevice( m_lastUsedDevice ); + return false; + } + + if( doc() ) { + m_cdParanoiaLib->setParanoiaMode( doc()->audioRippingParanoiaMode() ); + m_cdParanoiaLib->setNeverSkip( !doc()->audioRippingIgnoreReadErrors() ); + m_cdParanoiaLib->setMaxRetries( doc()->audioRippingRetries() ); + } + + m_cdParanoiaLib->initReading( m_toc[m_cdTrackNumber-1].firstSector().lba() + startOffset().lba() + m_position.lba(), + m_toc[m_cdTrackNumber-1].firstSector().lba() + lastSector().lba() ); + + // we only block during the initialization because we cannot determine the end of the reading process :( + k3bcore->unblockDevice( m_lastUsedDevice ); + + m_initialized = true; + kdDebug() << "(K3bAudioCdTrackSource) initialized." << endl; + } + } + + return m_initialized; +} + + +void K3bAudioCdTrackSource::closeParanoia() +{ + if( m_cdParanoiaLib && m_initialized ) { + m_cdParanoiaLib->close(); + } + m_initialized = false; +} + + +K3bDevice::Device* K3bAudioCdTrackSource::searchForAudioCD() const +{ + kdDebug() << "(K3bAudioCdTrackSource::searchForAudioCD()" << endl; + // first try the saved device + if( m_lastUsedDevice && searchForAudioCD( m_lastUsedDevice ) ) + return m_lastUsedDevice; + + const QPtrList& devices = k3bcore->deviceManager()->readingDevices(); + for( QPtrListIterator it(devices); *it; ++it ) { + if( searchForAudioCD( *it ) ) { + return *it; + } + } + + kdDebug() << "(K3bAudioCdTrackSource::searchForAudioCD) failed." << endl; + + return 0; +} + + +bool K3bAudioCdTrackSource::searchForAudioCD( K3bDevice::Device* dev ) const +{ + kdDebug() << "(K3bAudioCdTrackSource::searchForAudioCD(" << dev->description() << ")" << endl; + K3bDevice::Toc toc = dev->readToc(); + return ( toc.discId() == m_discId ); +} + + +void K3bAudioCdTrackSource::setDevice( K3bDevice::Device* dev ) +{ + if( dev && dev != m_lastUsedDevice ) { + m_lastUsedDevice = dev; + if( m_initialized ) { + } + } +} + + +K3b::Msf K3bAudioCdTrackSource::originalLength() const +{ + return m_length; +} + + +bool K3bAudioCdTrackSource::seek( const K3b::Msf& msf ) +{ + // HACK: to reinitialize every time we restart the decoding + if( msf == 0 && m_cdParanoiaLib ) + closeParanoia(); + + m_position = msf; + + if( m_cdParanoiaLib ) + m_cdParanoiaLib->initReading( m_toc[m_cdTrackNumber-1].firstSector().lba() + startOffset().lba() + m_position.lba(), + m_toc[m_cdTrackNumber-1].firstSector().lba() + lastSector().lba() ); + + return true; +} + + +int K3bAudioCdTrackSource::read( char* data, unsigned int ) +{ + if( initParanoia() ) { + int status = 0; + char* buf = m_cdParanoiaLib->read( &status, 0, false /* big endian */ ); + if( status == K3bCdparanoiaLib::S_OK ) { + if( buf == 0 ) { + // done + closeParanoia(); + return 0; + } + else { + ++m_position; + ::memcpy( data, buf, CD_FRAMESIZE_RAW ); + return CD_FRAMESIZE_RAW; + } + } + else { + // in case the reading fails we go back to "not initialized" + closeParanoia(); + return -1; + } + } + else + return -1; +} + + +QString K3bAudioCdTrackSource::type() const +{ + return i18n("CD Track"); +} + + +QString K3bAudioCdTrackSource::sourceComment() const +{ + return i18n("Track %1 from Audio CD %2").arg(m_cdTrackNumber).arg(m_discId,0,16); +} + + +K3bAudioDataSource* K3bAudioCdTrackSource::copy() const +{ + return new K3bAudioCdTrackSource( *this ); +} diff --git a/libk3b/projects/audiocd/k3baudiocdtracksource.h b/libk3b/projects/audiocd/k3baudiocdtracksource.h new file mode 100644 index 0000000..6eaaa5b --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiocdtracksource.h @@ -0,0 +1,99 @@ +/* + * + * $Id: k3baudiocdtracksource.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_CD_TRACK_SOURCE_H_ +#define _K3B_AUDIO_CD_TRACK_SOURCE_H_ + +#include "k3baudiodatasource.h" + +#include +#include + +#include "k3b_export.h" + + +namespace K3bDevice { + class Device; +} +class K3bCdparanoiaLib; + + +/** + * Audio data source which reads it's data directly from an audio CD. + * + * Be aware that since GUI elements are not allowed in sources (other thread) + * the source relies on the audio CD being inserted before any read operations. + * It will search all available devices for the CD starting with the last used drive. + */ +class LIBK3B_EXPORT K3bAudioCdTrackSource : public K3bAudioDataSource +{ + public: + /** + * Default constructor to create a new source. + */ + K3bAudioCdTrackSource( const K3bDevice::Toc& toc, int cdTrackNumber, const K3bCddbResultEntry& cddb, + K3bDevice::Device* dev = 0 ); + + /** + * Constructor to create sources when loading from a project file without toc information + */ + K3bAudioCdTrackSource( unsigned int discid, const K3b::Msf& length, int cdTrackNumber, + const QString& artist, const QString& title, + const QString& cdartist, const QString& cdtitle ); + K3bAudioCdTrackSource( const K3bAudioCdTrackSource& ); + ~K3bAudioCdTrackSource(); + + unsigned int discId() const { return m_discId; } + int cdTrackNumber() const { return m_cdTrackNumber; } + const K3bCddbResultEntry& metaInfo() const { return m_cddbEntry; } + + K3b::Msf originalLength() const; + bool seek( const K3b::Msf& ); + int read( char* data, unsigned int max ); + QString type() const; + QString sourceComment() const; + K3bAudioDataSource* copy() const; + + /** + * Searches for the corresponding Audio CD and returns the device in which it has + * been found or 0 if it could not be found. + */ + K3bDevice::Device* searchForAudioCD() const; + + /** + * Set the device the source should start to look for the CD. + */ + void setDevice( K3bDevice::Device* dev ); + + private: + bool initParanoia(); + void closeParanoia(); + bool searchForAudioCD( K3bDevice::Device* ) const; + + unsigned int m_discId; + K3b::Msf m_length; + K3bDevice::Toc m_toc; + int m_cdTrackNumber; + K3bCddbResultEntry m_cddbEntry; + + // ripping + // we only save the device we last saw the CD in + K3bDevice::Device* m_lastUsedDevice; + K3bCdparanoiaLib* m_cdParanoiaLib; + K3b::Msf m_position; + bool m_initialized; +}; + +#endif diff --git a/libk3b/projects/audiocd/k3baudiodatasource.cpp b/libk3b/projects/audiocd/k3baudiodatasource.cpp new file mode 100644 index 0000000..0f705f4 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiodatasource.cpp @@ -0,0 +1,210 @@ +/* + * + * $Id: k3baudiodatasource.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudiodatasource.h" +#include "k3baudiotrack.h" +#include "k3baudiodoc.h" + + +K3bAudioDataSource::K3bAudioDataSource() + : m_track(0), + m_prev(0), + m_next(0) +{ +} + + +K3bAudioDataSource::K3bAudioDataSource( const K3bAudioDataSource& source ) + : m_track( 0 ), + m_prev( 0 ), + m_next( 0 ), + m_startOffset( source.m_startOffset ), + m_endOffset( source.m_endOffset ) +{ +} + + +K3bAudioDataSource::~K3bAudioDataSource() +{ + take(); +} + + +K3bAudioDoc* K3bAudioDataSource::doc() const +{ + if( m_track ) + return m_track->doc(); + else + return 0; +} + + +K3bAudioDataSource* K3bAudioDataSource::take() +{ + // if we do not have a track we are not in any list + if( m_track ) { + if( !m_prev ) + m_track->setFirstSource( m_next ); + + if( m_prev ) + m_prev->m_next = m_next; + if( m_next ) + m_next->m_prev = m_prev; + + m_prev = m_next = 0; + + emitChange(); + m_track = 0; + } + + return this; +} + + +void K3bAudioDataSource::moveAfter( K3bAudioDataSource* source ) +{ + // cannot create a list outside a track! + if( !source->track() ) + return; + + if( source == this ) + return; + + // remove this from the list + take(); + + K3bAudioDataSource* oldNext = source->m_next; + + // set track as prev + source->m_next = this; + m_prev = source; + + // set oldNext as next + if( oldNext ) + oldNext->m_prev = this; + m_next = oldNext; + + m_track = source->track(); + emitChange(); +} + + +void K3bAudioDataSource::moveAhead( K3bAudioDataSource* source ) +{ + // cannot create a list outside a track! + if( !source->track() ) + return; + + if( source == this ) + return; + + // remove this from the list + take(); + + K3bAudioDataSource* oldPrev = source->m_prev; + + // set track as next + m_next = source; + source->m_prev = this; + + // set oldPrev as prev + m_prev = oldPrev; + if( oldPrev ) + oldPrev->m_next = this; + + m_track = source->track(); + + if( !m_prev ) + m_track->setFirstSource( this ); + + emitChange(); +} + + +void K3bAudioDataSource::emitChange() +{ + if( m_track ) + m_track->sourceChanged( this ); +} + + +K3bAudioDataSource* K3bAudioDataSource::split( const K3b::Msf& pos ) +{ + if( pos < length() ) { + K3bAudioDataSource* s = copy(); + s->setStartOffset( startOffset() + pos ); + s->setEndOffset( endOffset() ); + setEndOffset( startOffset() + pos ); + s->moveAfter( this ); + emitChange(); + return s; + } + else + return 0; +} + + +K3b::Msf K3bAudioDataSource::lastSector() const +{ + if( endOffset() > 0 ) + return endOffset()-1; + else + return originalLength()-1; +} + + +K3b::Msf K3bAudioDataSource::length() const +{ + if( originalLength() == 0 ) + return 0; + else if( lastSector() < m_startOffset ) + return 1; + else + return lastSector() - m_startOffset + 1; +} + + +void K3bAudioDataSource::setStartOffset( const K3b::Msf& msf ) +{ + m_startOffset = msf; + fixupOffsets(); + emitChange(); +} + + +void K3bAudioDataSource::setEndOffset( const K3b::Msf& msf ) +{ + m_endOffset = msf; + fixupOffsets(); + emitChange(); +} + + +void K3bAudioDataSource::fixupOffsets() +{ + // no length available yet + if( originalLength() == 0 ) + return; + + if( startOffset() >= originalLength() ) { + setStartOffset( 0 ); + } + if( endOffset() > originalLength() ) { + setEndOffset( 0 ); // whole source + } + if( endOffset() > 0 && endOffset() <= startOffset() ) { + setEndOffset( startOffset() ); + } +} diff --git a/libk3b/projects/audiocd/k3baudiodatasource.h b/libk3b/projects/audiocd/k3baudiodatasource.h new file mode 100644 index 0000000..d12fd10 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiodatasource.h @@ -0,0 +1,168 @@ +/* + * + * $Id: k3baudiodatasource.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_DATA_SOURCE_H_ +#define _K3B_AUDIO_DATA_SOURCE_H_ + +#include +#include "k3b_export.h" +class K3bAudioTrack; +class K3bAudioDoc; + + +/** + * An AudioDataSource has an original length which represents the maximum amount of audio + * sectors this source can provide (in special cases this is not true, see K3bAudioZeroData). + * + * It is possible to just use a portion of that data by changing the startOffset and endOffset. + * This will change the actual length of the data provided by this source through the read method. + * + * Sources are part of a list which can be traversed via the prev() and next() methods. This list + * is part of a K3bAudioTrack which in turn is part of a list which is owned by a K3bAudioDoc. + * + * The list may be modified with the take(), moveAfter(), and moveAhead() methods. The source takes + * care of fixing the list and notifying the track about the change (It is also possible to move sources + * from one track to the other). + * + * When a source is deleted it automatically removes itself from it's list. + */ +class LIBK3B_EXPORT K3bAudioDataSource +{ + friend class K3bAudioTrack; + + public: + K3bAudioDataSource(); + + /** + * Create en identical copy except that the copy will not be in any list. + */ + K3bAudioDataSource( const K3bAudioDataSource& ); + virtual ~K3bAudioDataSource(); + + /** + * The original length of the source is the maximum data which is available + * when startOffset is 0 this is the max for endOffset + * + * Be aware that this may change (see K3bAudioZeroData) + */ + virtual K3b::Msf originalLength() const = 0; + + /** + * The default implementation returns the originalLength modified by startOffset and endOffset + */ + virtual K3b::Msf length() const; + + /** + * @return The raw size in pcm samples (16bit, 44800 kHz, stereo) + */ + KIO::filesize_t size() const { return length().audioBytes(); } + + virtual bool seek( const K3b::Msf& ) = 0; + + /** + * Read data from the source. + */ + virtual int read( char* data, unsigned int max ) = 0; + + /** + * Type of the data in readable form. + */ + virtual QString type() const = 0; + + /** + * The source in readable form (this is the filename for files) + */ + virtual QString sourceComment() const = 0; + + /** + * Used in case an error occurred. For now this is used if the + * decoder was not able to decode an audiofile + */ + virtual bool isValid() const { return true; } + + /** + * The doc the source is currently a part of or null. + */ + K3bAudioDoc* doc() const; + K3bAudioTrack* track() const { return m_track; } + + K3bAudioDataSource* prev() const { return m_prev; } + K3bAudioDataSource* next() const { return m_next; } + + K3bAudioDataSource* take(); + + void moveAfter( K3bAudioDataSource* track ); + void moveAhead( K3bAudioDataSource* track ); + + /** + * Set the start offset from the beginning of the source's originalLength. + */ + virtual void setStartOffset( const K3b::Msf& ); + + /** + * Set the end offset from the beginning of the file. The endOffset sector + * is not included in the data. + * The maximum value is originalLength() which means to use all data. + * 0 means the same as originalLength(). + * This has to be bigger than the start offset. + */ + virtual void setEndOffset( const K3b::Msf& ); + + virtual const K3b::Msf& startOffset() const { return m_startOffset; } + + /** + * The end offset. It is the first sector not included in the data. + * If 0 the last sector is determined by the originalLength + */ + virtual const K3b::Msf& endOffset() const { return m_endOffset; } + + /** + * Get the last used sector in the source. + * The default implementation uses originalLength() and endOffset() + */ + virtual K3b::Msf lastSector() const; + + /** + * Create a copy of this source which is not part of a list + */ + virtual K3bAudioDataSource* copy() const = 0; + + /** + * Split the source at position pos and return the splitted source + * on success. + * The new source will be moved after this source. + * + * The default implementation uses copy() to create a new source instance + */ + virtual K3bAudioDataSource* split( const K3b::Msf& pos ); + + protected: + /** + * Informs the parent track about changes. + */ + void emitChange(); + + private: + void fixupOffsets(); + + K3bAudioTrack* m_track; + K3bAudioDataSource* m_prev; + K3bAudioDataSource* m_next; + + K3b::Msf m_startOffset; + K3b::Msf m_endOffset; +}; + +#endif diff --git a/libk3b/projects/audiocd/k3baudiodatasourceiterator.cpp b/libk3b/projects/audiocd/k3baudiodatasourceiterator.cpp new file mode 100644 index 0000000..81e0a59 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiodatasourceiterator.cpp @@ -0,0 +1,71 @@ +/* + * + * $Id: sourceheader,v 1.3 2005/01/19 13:03:46 trueg Exp $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudiodatasourceiterator.h" +#include "k3baudiodoc.h" +#include "k3baudiotrack.h" +#include "k3baudiodatasource.h" + + +K3bAudioDataSourceIterator::K3bAudioDataSourceIterator( K3bAudioDoc* doc ) + : m_doc( doc ) +{ + first(); +} + + +K3bAudioDataSource* K3bAudioDataSourceIterator::current() const +{ + return m_currentSource; +} + + +K3bAudioDataSource* K3bAudioDataSourceIterator::next() +{ + m_currentSource = m_currentSource->next(); + if( !m_currentSource ) { + m_currentTrack = m_currentTrack->next(); + if( m_currentTrack ) + m_currentSource = m_currentTrack->firstSource(); + } + + return m_currentSource; +} + + +bool K3bAudioDataSourceIterator::hasNext() const +{ + if( !m_currentSource ) + return false; + if( m_currentSource->next() ) + return true; + if( m_currentTrack->next() ) + return true; + + return false; +} + + +K3bAudioDataSource* K3bAudioDataSourceIterator::first() +{ + m_currentTrack = m_doc->firstTrack(); + + if( m_currentTrack ) + m_currentSource = m_currentTrack->firstSource(); + else + m_currentSource = 0; + + return m_currentSource; +} diff --git a/libk3b/projects/audiocd/k3baudiodatasourceiterator.h b/libk3b/projects/audiocd/k3baudiodatasourceiterator.h new file mode 100644 index 0000000..7a0ce59 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiodatasourceiterator.h @@ -0,0 +1,61 @@ +/* + * + * $Id: sourceheader,v 1.3 2005/01/19 13:03:46 trueg Exp $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_DATA_SOURCE_ITERATOR_H_ +#define _K3B_AUDIO_DATA_SOURCE_ITERATOR_H_ +#include "k3b_export.h" +class K3bAudioDataSource; +class K3bAudioTrack; +class K3bAudioDoc; + + +/** + * This Iterator iterates over the sources in an audio project + * + * Be aware that this iterator does not properly update when the doc + * changes. A manual update can be issued with first(). This is becasue + * an update would either involve slots (this being a QObject) which is + * too much overhead or the AudioDoc would need to have knowledge of all + * the iterators which is also overhead that would be overkill. + */ +class LIBK3B_EXPORT K3bAudioDataSourceIterator +{ + public: + /** + * This will place the iterator on the first source just like first() does. + */ + explicit K3bAudioDataSourceIterator( K3bAudioDoc* ); + + K3bAudioDataSource* current() const; + + bool hasNext() const; + + /** + * \return the next source or 0 if at end. + */ + K3bAudioDataSource* next(); + + /** + * Reset the iterator + */ + K3bAudioDataSource* first(); + + private: + K3bAudioDoc* m_doc; + K3bAudioTrack* m_currentTrack; + K3bAudioDataSource* m_currentSource; +}; + +#endif diff --git a/libk3b/projects/audiocd/k3baudiodoc.cpp b/libk3b/projects/audiocd/k3baudiodoc.cpp new file mode 100644 index 0000000..e7661ba --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiodoc.cpp @@ -0,0 +1,1127 @@ +/* + * + * $Id: k3baudiodoc.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include +#include "k3baudiodoc.h" +#include "k3baudiotrack.h" +#include "k3baudiojob.h" +#include "k3baudiofile.h" +#include "k3baudiozerodata.h" +#include "k3baudiocdtracksource.h" + +#include +#include +#include +#include + + +// QT-includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// KDE-includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +class K3bAudioDoc::Private +{ +public: + Private() { + cdTextValidator = new K3bCdTextValidator(); + } + + ~Private() { + delete cdTextValidator; + } + + K3bCdTextValidator* cdTextValidator; +}; + + +K3bAudioDoc::K3bAudioDoc( QObject* parent ) + : K3bDoc( parent ), + m_firstTrack(0), + m_lastTrack(0) +{ + d = new Private; + m_docType = AUDIO; +} + +K3bAudioDoc::~K3bAudioDoc() +{ + // delete all tracks + int i = 1; + int cnt = numOfTracks(); + while( m_firstTrack ) { + kdDebug() << "(K3bAudioDoc::~K3bAudioDoc) deleting track " << i << " of " << cnt << endl; + delete m_firstTrack->take(); + kdDebug() << "(K3bAudioDoc::~K3bAudioDoc) deleted." << endl; + ++i; + } + + delete d; +} + +bool K3bAudioDoc::newDocument() +{ + // delete all tracks + while( m_firstTrack ) + delete m_firstTrack->take(); + + m_normalize = false; + m_hideFirstTrack = false; + m_cdText = false; + m_cdTextData.clear(); + m_audioRippingParanoiaMode = 0; + m_audioRippingRetries = 5; + m_audioRippingIgnoreReadErrors = true; + + return K3bDoc::newDocument(); +} + + +QString K3bAudioDoc::name() const +{ + if( !m_cdTextData.title().isEmpty() ) + return m_cdTextData.title(); + else + return K3bDoc::name(); +} + + +K3bAudioTrack* K3bAudioDoc::firstTrack() const +{ + return m_firstTrack; +} + + +K3bAudioTrack* K3bAudioDoc::lastTrack() const +{ + return m_lastTrack; +} + + +// this one is called by K3bAudioTrack to update the list +void K3bAudioDoc::setFirstTrack( K3bAudioTrack* track ) +{ + m_firstTrack = track; +} + +// this one is called by K3bAudioTrack to update the list +void K3bAudioDoc::setLastTrack( K3bAudioTrack* track ) +{ + m_lastTrack = track; +} + + +KIO::filesize_t K3bAudioDoc::size() const +{ + // This is not really correct but what the user expects ;) + return length().mode1Bytes(); +} + + +K3b::Msf K3bAudioDoc::length() const +{ + K3b::Msf length = 0; + K3bAudioTrack* track = m_firstTrack; + while( track ) { + length += track->length(); + track = track->next(); + } + + return length; +} + + +void K3bAudioDoc::addUrls( const KURL::List& urls ) +{ + // make sure we add them at the end even if urls are in the queue + addTracks( urls, 99 ); +} + + +void K3bAudioDoc::addTracks( const KURL::List& urls, uint position ) +{ + KURL::List allUrls = extractUrlList( K3b::convertToLocalUrls(urls) ); + KURL::List::iterator end( allUrls.end()); + for( KURL::List::iterator it = allUrls.begin(); it != end; it++, position++ ) { + KURL& url = *it; + if( url.path().right(3).lower() == "cue" ) { + // try adding a cue file + if( K3bAudioTrack* newAfter = importCueFile( url.path(), getTrack(position) ) ) { + position = newAfter->trackNumber(); + continue; + } + } + + if( K3bAudioTrack* track = createTrack( url ) ) { + addTrack( track, position ); + + K3bAudioDecoder* dec = static_cast( track->firstSource() )->decoder(); + track->setTitle( dec->metaInfo( K3bAudioDecoder::META_TITLE ) ); + track->setArtist( dec->metaInfo( K3bAudioDecoder::META_ARTIST ) ); + track->setSongwriter( dec->metaInfo( K3bAudioDecoder::META_SONGWRITER ) ); + track->setComposer( dec->metaInfo( K3bAudioDecoder::META_COMPOSER ) ); + track->setCdTextMessage( dec->metaInfo( K3bAudioDecoder::META_COMMENT ) ); + } + } + + emit changed(); + + informAboutNotFoundFiles(); +} + + +KURL::List K3bAudioDoc::extractUrlList( const KURL::List& urls ) +{ + KURL::List allUrls = urls; + KURL::List urlsFromPlaylist; + KURL::List::iterator it = allUrls.begin(); + while( it != allUrls.end() ) { + + const KURL& url = *it; + QFileInfo fi( url.path() ); + + if( !url.isLocalFile() ) { + kdDebug() << url.path() << " no local file" << endl; + it = allUrls.remove( it ); + m_notFoundFiles.append( url ); + } + else if( !fi.exists() ) { + it = allUrls.remove( it ); + kdDebug() << url.path() << " not found" << endl; + m_notFoundFiles.append( url ); + } + else if( fi.isDir() ) { + it = allUrls.remove( it ); + // add all files in the dir + QDir dir(fi.filePath()); + QStringList entries = dir.entryList( QDir::Files ); + KURL::List::iterator oldIt = it; + // add all files into the list after the current item + for( QStringList::iterator dirIt = entries.begin(); + dirIt != entries.end(); ++dirIt ) + it = allUrls.insert( oldIt, KURL::fromPathOrURL( dir.absPath() + "/" + *dirIt ) ); + } + else if( readPlaylistFile( url, urlsFromPlaylist ) ) { + it = allUrls.remove( it ); + KURL::List::iterator oldIt = it; + // add all files into the list after the current item + for( KURL::List::iterator dirIt = urlsFromPlaylist.begin(); + dirIt != urlsFromPlaylist.end(); ++dirIt ) + it = allUrls.insert( oldIt, *dirIt ); + } + else + ++it; + } + + return allUrls; +} + + +bool K3bAudioDoc::readPlaylistFile( const KURL& url, KURL::List& playlist ) +{ + // check if the file is a m3u playlist + // and if so add all listed files + + QFile f( url.path() ); + if( !f.open( IO_ReadOnly ) ) + return false; + + QTextStream t( &f ); + char buf[7]; + t.readRawBytes( buf, 7 ); + if( QString::fromLatin1( buf, 7 ) != "#EXTM3U" ) + return false; + + // skip the first line + t.readLine(); + + // read the file + while( !t.atEnd() ) { + QString line = t.readLine(); + if( line[0] != '#' ) { + KURL mp3url; + // relative paths + if( line[0] != '/' ) + mp3url.setPath( url.directory(false) + line ); + else + mp3url.setPath( line ); + + playlist.append( mp3url ); + } + } + + return true; +} + + +void K3bAudioDoc::addSources( K3bAudioTrack* parent, + const KURL::List& urls, + K3bAudioDataSource* sourceAfter ) +{ + kdDebug() << "(K3bAudioDoc::addSources( " << parent << ", " + << urls.first().path() << ", " + << sourceAfter << " )" << endl; + KURL::List allUrls = extractUrlList( urls ); + KURL::List::const_iterator end(allUrls.end()); + for( KURL::List::const_iterator it = allUrls.begin(); it != end; ++it ) { + if( K3bAudioFile* file = createAudioFile( *it ) ) { + if( sourceAfter ) + file->moveAfter( sourceAfter ); + else + file->moveAhead( parent->firstSource() ); + sourceAfter = file; + } + } + + informAboutNotFoundFiles(); + kdDebug() << "(K3bAudioDoc::addSources) finished." << endl; +} + + +K3bAudioTrack* K3bAudioDoc::importCueFile( const QString& cuefile, K3bAudioTrack* after, K3bAudioDecoder* decoder ) +{ + if( !after ) + after = m_lastTrack; + + kdDebug() << "(K3bAudioDoc::importCueFile( " << cuefile << ", " << after << ")" << endl; + K3bCueFileParser parser( cuefile ); + if( parser.isValid() && parser.toc().contentType() == K3bDevice::AUDIO ) { + + kdDebug() << "(K3bAudioDoc::importCueFile) parsed with image: " << parser.imageFilename() << endl; + + // global cd-text + if( !parser.cdText().title().isEmpty() ) + setTitle( parser.cdText().title() ); + if( !parser.cdText().performer().isEmpty() ) + setPerformer( parser.cdText().performer() ); + + bool reused = true; + if( !decoder ) + decoder = getDecoderForUrl( KURL::fromPathOrURL(parser.imageFilename()), &reused ); + + if( decoder ) { + if( !reused ) + decoder->analyseFile(); + + K3bAudioFile* newFile = 0; + unsigned int i = 0; + for( K3bDevice::Toc::const_iterator it = parser.toc().begin(); + it != parser.toc().end(); ++it ) { + const K3bDevice::Track& track = *it; + + newFile = new K3bAudioFile( decoder, this ); + newFile->setStartOffset( track.firstSector() ); + newFile->setEndOffset( track.lastSector()+1 ); + + K3bAudioTrack* newTrack = new K3bAudioTrack( this ); + newTrack->addSource( newFile ); + newTrack->moveAfter( after ); + + // we do not know the length of the source yet so we have to force the index value + if( track.index0() > 0 ) + newTrack->m_index0Offset = track.length() - track.index0(); + else + newTrack->m_index0Offset = 0; + + // cd-text + newTrack->setTitle( parser.cdText()[i].title() ); + newTrack->setPerformer( parser.cdText()[i].performer() ); + + // add the next track after this one + after = newTrack; + ++i; + } + + // let the last source use the data up to the end of the file + if( newFile ) + newFile->setEndOffset(0); + + return after; + } + } + return 0; +} + + +K3bAudioDecoder* K3bAudioDoc::getDecoderForUrl( const KURL& url, bool* reused ) +{ + K3bAudioDecoder* decoder = 0; + + // check if we already have a proper decoder + if( m_decoderPresenceMap.contains( url.path() ) ) { + decoder = m_decoderPresenceMap[url.path()]; + *reused = true; + } + else if( (decoder = K3bAudioDecoderFactory::createDecoder( url )) ) { + kdDebug() << "(K3bAudioDoc) using " << decoder->className() + << " for decoding of " << url.path() << endl; + + decoder->setFilename( url.path() ); + *reused = false; + } + + return decoder; +} + + +K3bAudioFile* K3bAudioDoc::createAudioFile( const KURL& url ) +{ + if( !QFile::exists( url.path() ) ) { + m_notFoundFiles.append( url.path() ); + kdDebug() << "(K3bAudioDoc) could not find file " << url.path() << endl; + return 0; + } + + bool reused; + K3bAudioDecoder* decoder = getDecoderForUrl( url, &reused ); + if( decoder ) { + if( !reused ) + decoder->analyseFile(); + return new K3bAudioFile( decoder, this ); + } + else { + m_unknownFileFormatFiles.append( url.path() ); + kdDebug() << "(K3bAudioDoc) unknown file type in file " << url.path() << endl; + return 0; + } +} + + +K3bAudioTrack* K3bAudioDoc::createTrack( const KURL& url ) +{ + kdDebug() << "(K3bAudioDoc::createTrack( " << url.path() << " )" << endl; + if( K3bAudioFile* file = createAudioFile( url ) ) { + K3bAudioTrack* newTrack = new K3bAudioTrack( this ); + newTrack->setFirstSource( file ); + return newTrack; + } + else + return 0; +} + + +void K3bAudioDoc::addTrack( const KURL& url, uint position ) +{ + addTracks( KURL::List(url), position ); +} + + + +K3bAudioTrack* K3bAudioDoc::getTrack( unsigned int trackNum ) +{ + K3bAudioTrack* track = m_firstTrack; + unsigned int i = 1; + while( track ) { + if( i == trackNum ) + return track; + track = track->next(); + ++i; + } + + return 0; +} + + +void K3bAudioDoc::addTrack( K3bAudioTrack* track, uint position ) +{ + kdDebug() << "(K3bAudioDoc::addTrack( " << track << ", " << position << " )" << endl; + track->m_parent = this; + if( !m_firstTrack ) + m_firstTrack = m_lastTrack = track; + else if( position == 0 ) + track->moveAhead( m_firstTrack ); + else { + K3bAudioTrack* after = getTrack( position ); + if( after ) + track->moveAfter( after ); + else + track->moveAfter( m_lastTrack ); // just to be sure it's anywhere... + } + + emit changed(); +} + + +void K3bAudioDoc::removeTrack( K3bAudioTrack* track ) +{ + delete track; +} + + +void K3bAudioDoc::moveTrack( K3bAudioTrack* track, K3bAudioTrack* after ) +{ + track->moveAfter( after ); +} + + +QString K3bAudioDoc::typeString() const +{ + return "audio"; +} + + +bool K3bAudioDoc::loadDocumentData( QDomElement* root ) +{ + newDocument(); + + // we will parse the dom-tree and create a K3bAudioTrack for all entries immediately + // this should not take long and so not block the gui + + QDomNodeList nodes = root->childNodes(); + + for( uint i = 0; i < nodes.count(); i++ ) { + + QDomElement e = nodes.item(i).toElement(); + + if( e.isNull() ) + return false; + + if( e.nodeName() == "general" ) { + if( !readGeneralDocumentData( e ) ) + return false; + } + + else if( e.nodeName() == "normalize" ) + setNormalize( e.text() == "yes" ); + + else if( e.nodeName() == "hide_first_track" ) + setHideFirstTrack( e.text() == "yes" ); + + else if( e.nodeName() == "audio_ripping" ) { + QDomNodeList ripNodes = e.childNodes(); + for( uint j = 0; j < ripNodes.length(); j++ ) { + if( ripNodes.item(j).nodeName() == "paranoia_mode" ) + setAudioRippingParanoiaMode( ripNodes.item(j).toElement().text().toInt() ); + else if( ripNodes.item(j).nodeName() == "read_retries" ) + setAudioRippingRetries( ripNodes.item(j).toElement().text().toInt() ); + else if( ripNodes.item(j).nodeName() == "ignore_read_errors" ) + setAudioRippingIgnoreReadErrors( ripNodes.item(j).toElement().text() == "yes" ); + } + } + + // parse cd-text + else if( e.nodeName() == "cd-text" ) { + if( !e.hasAttribute( "activated" ) ) + return false; + + writeCdText( e.attributeNode( "activated" ).value() == "yes" ); + + QDomNodeList cdTextNodes = e.childNodes(); + for( uint j = 0; j < cdTextNodes.length(); j++ ) { + if( cdTextNodes.item(j).nodeName() == "title" ) + setTitle( cdTextNodes.item(j).toElement().text() ); + + else if( cdTextNodes.item(j).nodeName() == "artist" ) + setArtist( cdTextNodes.item(j).toElement().text() ); + + else if( cdTextNodes.item(j).nodeName() == "arranger" ) + setArranger( cdTextNodes.item(j).toElement().text() ); + + else if( cdTextNodes.item(j).nodeName() == "songwriter" ) + setSongwriter( cdTextNodes.item(j).toElement().text() ); + + else if( cdTextNodes.item(j).nodeName() == "composer" ) + setComposer( cdTextNodes.item(j).toElement().text() ); + + else if( cdTextNodes.item(j).nodeName() == "disc_id" ) + setDisc_id( cdTextNodes.item(j).toElement().text() ); + + else if( cdTextNodes.item(j).nodeName() == "upc_ean" ) + setUpc_ean( cdTextNodes.item(j).toElement().text() ); + + else if( cdTextNodes.item(j).nodeName() == "message" ) + setCdTextMessage( cdTextNodes.item(j).toElement().text() ); + } + } + + else if( e.nodeName() == "contents" ) { + + QDomNodeList contentNodes = e.childNodes(); + + for( uint j = 0; j< contentNodes.length(); j++ ) { + + QDomElement trackElem = contentNodes.item(j).toElement(); + + // first of all we need a track + K3bAudioTrack* track = new K3bAudioTrack(); + + + // backwards compatibility + // ----------------------------------------------------------------------------------------------------- + QDomAttr oldUrlAttr = trackElem.attributeNode( "url" ); + if( !oldUrlAttr.isNull() ) { + if( K3bAudioFile* file = + createAudioFile( KURL::fromPathOrURL( oldUrlAttr.value() ) ) ) { + track->addSource( file ); + } + } + // ----------------------------------------------------------------------------------------------------- + + + QDomNodeList trackNodes = trackElem.childNodes(); + for( uint trackJ = 0; trackJ < trackNodes.length(); trackJ++ ) { + + if( trackNodes.item(trackJ).nodeName() == "sources" ) { + QDomNodeList sourcesNodes = trackNodes.item(trackJ).childNodes(); + for( unsigned int sourcesIndex = 0; sourcesIndex < sourcesNodes.length(); sourcesIndex++ ) { + QDomElement sourceElem = sourcesNodes.item(sourcesIndex).toElement(); + if( sourceElem.nodeName() == "file" ) { + if( K3bAudioFile* file = + createAudioFile( KURL::fromPathOrURL( sourceElem.attributeNode( "url" ).value() ) ) ) { + file->setStartOffset( K3b::Msf::fromString( sourceElem.attributeNode( "start_offset" ).value() ) ); + file->setEndOffset( K3b::Msf::fromString( sourceElem.attributeNode( "end_offset" ).value() ) ); + track->addSource( file ); + } + } + else if( sourceElem.nodeName() == "silence" ) { + K3bAudioZeroData* zero = new K3bAudioZeroData(); + zero->setLength( K3b::Msf::fromString( sourceElem.attributeNode( "length" ).value() ) ); + track->addSource( zero ); + } + else if( sourceElem.nodeName() == "cdtrack" ) { + K3b::Msf length = K3b::Msf::fromString( sourceElem.attributeNode( "length" ).value() ); + int titlenum = 0; + unsigned int discid = 0; + QString title, artist, cdTitle, cdArtist; + + QDomNodeList cdTrackSourceNodes = sourceElem.childNodes(); + for( unsigned int cdTrackSourceIndex = 0; cdTrackSourceIndex < cdTrackSourceNodes.length(); ++cdTrackSourceIndex ) { + QDomElement cdTrackSourceItemElem = cdTrackSourceNodes.item(cdTrackSourceIndex).toElement(); + if( cdTrackSourceItemElem.nodeName() == "title_number" ) + titlenum = cdTrackSourceItemElem.text().toInt(); + else if( cdTrackSourceItemElem.nodeName() == "disc_id" ) + discid = cdTrackSourceItemElem.text().toUInt( 0, 16 ); + else if( cdTrackSourceItemElem.nodeName() == "title" ) + title = cdTrackSourceItemElem.text().toInt(); + else if( cdTrackSourceItemElem.nodeName() == "artist" ) + artist = cdTrackSourceItemElem.text().toInt(); + else if( cdTrackSourceItemElem.nodeName() == "cdtitle" ) + cdTitle = cdTrackSourceItemElem.text().toInt(); + else if( cdTrackSourceItemElem.nodeName() == "cdartist" ) + cdArtist = cdTrackSourceItemElem.text().toInt(); + } + + if( discid != 0 && titlenum > 0 ) { + K3bAudioCdTrackSource* cdtrack = new K3bAudioCdTrackSource( discid, length, titlenum, + artist, title, + cdArtist, cdTitle ); + cdtrack->setStartOffset( K3b::Msf::fromString( sourceElem.attributeNode( "start_offset" ).value() ) ); + cdtrack->setEndOffset( K3b::Msf::fromString( sourceElem.attributeNode( "end_offset" ).value() ) ); + track->addSource( cdtrack ); + } + else { + kdDebug() << "(K3bAudioDoc) invalid cdtrack source." << endl; + return false; + } + } + else { + kdDebug() << "(K3bAudioDoc) unknown source type: " << sourceElem.nodeName() << endl; + return false; + } + } + } + + // load cd-text + else if( trackNodes.item(trackJ).nodeName() == "cd-text" ) { + QDomNodeList cdTextNodes = trackNodes.item(trackJ).childNodes(); + for( uint trackCdTextJ = 0; trackCdTextJ < cdTextNodes.length(); trackCdTextJ++ ) { + if( cdTextNodes.item(trackCdTextJ).nodeName() == "title" ) + track->setTitle( cdTextNodes.item(trackCdTextJ).toElement().text() ); + + else if( cdTextNodes.item(trackCdTextJ).nodeName() == "artist" ) + track->setArtist( cdTextNodes.item(trackCdTextJ).toElement().text() ); + + else if( cdTextNodes.item(trackCdTextJ).nodeName() == "arranger" ) + track->setArranger( cdTextNodes.item(trackCdTextJ).toElement().text() ); + + else if( cdTextNodes.item(trackCdTextJ).nodeName() == "songwriter" ) + track->setSongwriter( cdTextNodes.item(trackCdTextJ).toElement().text() ); + + else if( cdTextNodes.item(trackCdTextJ).nodeName() == "composer" ) + track->setComposer( cdTextNodes.item(trackCdTextJ).toElement().text() ); + + else if( cdTextNodes.item(trackCdTextJ).nodeName() == "isrc" ) + track->setIsrc( cdTextNodes.item(trackCdTextJ).toElement().text() ); + + else if( cdTextNodes.item(trackCdTextJ).nodeName() == "message" ) + track->setCdTextMessage( cdTextNodes.item(trackCdTextJ).toElement().text() ); + } + } + + else if( trackNodes.item(trackJ).nodeName() == "index0" ) + track->setIndex0( K3b::Msf::fromString( trackNodes.item(trackJ).toElement().text() ) ); + + // TODO: load other indices + + // load options + else if( trackNodes.item(trackJ).nodeName() == "copy_protection" ) + track->setCopyProtection( trackNodes.item(trackJ).toElement().text() == "yes" ); + + else if( trackNodes.item(trackJ).nodeName() == "pre_emphasis" ) + track->setPreEmp( trackNodes.item(trackJ).toElement().text() == "yes" ); + } + + // add the track + if( track->numberSources() > 0 ) + addTrack( track, 99 ); // append to the end // TODO improve + else { + kdDebug() << "(K3bAudioDoc) no sources. deleting track " << track << endl; + delete track; + } + } + } + } + + informAboutNotFoundFiles(); + + setModified(false); + + return true; +} + +bool K3bAudioDoc::saveDocumentData( QDomElement* docElem ) +{ + QDomDocument doc = docElem->ownerDocument(); + saveGeneralDocumentData( docElem ); + + // add normalize + QDomElement normalizeElem = doc.createElement( "normalize" ); + normalizeElem.appendChild( doc.createTextNode( normalize() ? "yes" : "no" ) ); + docElem->appendChild( normalizeElem ); + + // add hide track + QDomElement hideFirstTrackElem = doc.createElement( "hide_first_track" ); + hideFirstTrackElem.appendChild( doc.createTextNode( hideFirstTrack() ? "yes" : "no" ) ); + docElem->appendChild( hideFirstTrackElem ); + + // save the audio cd ripping settings + // paranoia mode, read retries, and ignore read errors + // ------------------------------------------------------------ + QDomElement ripMain = doc.createElement( "audio_ripping" ); + docElem->appendChild( ripMain ); + + QDomElement ripElem = doc.createElement( "paranoia_mode" ); + ripElem.appendChild( doc.createTextNode( QString::number( audioRippingParanoiaMode() ) ) ); + ripMain.appendChild( ripElem ); + + ripElem = doc.createElement( "read_retries" ); + ripElem.appendChild( doc.createTextNode( QString::number( audioRippingRetries() ) ) ); + ripMain.appendChild( ripElem ); + + ripElem = doc.createElement( "ignore_read_errors" ); + ripElem.appendChild( doc.createTextNode( audioRippingIgnoreReadErrors() ? "yes" : "no" ) ); + ripMain.appendChild( ripElem ); + // ------------------------------------------------------------ + + // save disc cd-text + // ------------------------------------------------------------- + QDomElement cdTextMain = doc.createElement( "cd-text" ); + cdTextMain.setAttribute( "activated", cdText() ? "yes" : "no" ); + QDomElement cdTextElem = doc.createElement( "title" ); + cdTextElem.appendChild( doc.createTextNode( (title())) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "artist" ); + cdTextElem.appendChild( doc.createTextNode( (artist())) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "arranger" ); + cdTextElem.appendChild( doc.createTextNode( (arranger())) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "songwriter" ); + cdTextElem.appendChild( doc.createTextNode( (songwriter())) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "composer" ); + cdTextElem.appendChild( doc.createTextNode( composer()) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "disc_id" ); + cdTextElem.appendChild( doc.createTextNode( (disc_id())) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "upc_ean" ); + cdTextElem.appendChild( doc.createTextNode( (upc_ean())) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "message" ); + cdTextElem.appendChild( doc.createTextNode( (cdTextMessage())) ); + cdTextMain.appendChild( cdTextElem ); + + docElem->appendChild( cdTextMain ); + // ------------------------------------------------------------- + + // save the tracks + // ------------------------------------------------------------- + QDomElement contentsElem = doc.createElement( "contents" ); + + for( K3bAudioTrack* track = firstTrack(); track != 0; track = track->next() ) { + + QDomElement trackElem = doc.createElement( "track" ); + + // add sources + QDomElement sourcesParent = doc.createElement( "sources" ); + + for( K3bAudioDataSource* source = track->firstSource(); source; source = source->next() ) { + // TODO: save a source element with a type attribute and start- and endoffset + // then distict between the different source types. + if( K3bAudioFile* file = dynamic_cast(source) ) { + QDomElement sourceElem = doc.createElement( "file" ); + sourceElem.setAttribute( "url", file->filename() ); + sourceElem.setAttribute( "start_offset", file->startOffset().toString() ); + sourceElem.setAttribute( "end_offset", file->endOffset().toString() ); + sourcesParent.appendChild( sourceElem ); + } + else if( K3bAudioZeroData* zero = dynamic_cast(source) ) { + QDomElement sourceElem = doc.createElement( "silence" ); + sourceElem.setAttribute( "length", zero->length().toString() ); + sourcesParent.appendChild( sourceElem ); + } + else if( K3bAudioCdTrackSource* cdTrack = dynamic_cast(source) ) { + QDomElement sourceElem = doc.createElement( "cdtrack" ); + sourceElem.setAttribute( "length", cdTrack->originalLength().toString() ); + sourceElem.setAttribute( "start_offset", cdTrack->startOffset().toString() ); + sourceElem.setAttribute( "end_offset", cdTrack->endOffset().toString() ); + + QDomElement subElem = doc.createElement( "title_number" ); + subElem.appendChild( doc.createTextNode( QString::number(cdTrack->cdTrackNumber()) ) ); + sourceElem.appendChild( subElem ); + + subElem = doc.createElement( "disc_id" ); + subElem.appendChild( doc.createTextNode( QString::number(cdTrack->discId(), 16) ) ); + sourceElem.appendChild( subElem ); + + subElem = doc.createElement( "title" ); + subElem.appendChild( doc.createTextNode( cdTrack->metaInfo().titles[cdTrack->cdTrackNumber()-1] ) ); + sourceElem.appendChild( subElem ); + + subElem = doc.createElement( "artist" ); + subElem.appendChild( doc.createTextNode( cdTrack->metaInfo().artists[cdTrack->cdTrackNumber()-1] ) ); + sourceElem.appendChild( subElem ); + + subElem = doc.createElement( "cdtitle" ); + subElem.appendChild( doc.createTextNode( cdTrack->metaInfo().cdTitle ) ); + sourceElem.appendChild( subElem ); + + subElem = doc.createElement( "cdartist" ); + subElem.appendChild( doc.createTextNode( cdTrack->metaInfo().cdArtist ) ); + sourceElem.appendChild( subElem ); + + sourcesParent.appendChild( sourceElem ); + } + else { + kdError() << "(K3bAudioDoc) saving sources other than file or zero not supported yet." << endl; + return false; + } + } + trackElem.appendChild( sourcesParent ); + + // index 0 + QDomElement index0Elem = doc.createElement( "index0" ); + index0Elem.appendChild( doc.createTextNode( track->index0().toString() ) ); + trackElem.appendChild( index0Elem ); + + // TODO: other indices + + // add cd-text + cdTextMain = doc.createElement( "cd-text" ); + cdTextElem = doc.createElement( "title" ); + cdTextElem.appendChild( doc.createTextNode( (track->title())) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "artist" ); + cdTextElem.appendChild( doc.createTextNode( (track->artist())) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "arranger" ); + cdTextElem.appendChild( doc.createTextNode( (track->arranger()) ) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "songwriter" ); + cdTextElem.appendChild( doc.createTextNode( (track->songwriter()) ) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "composer" ); + cdTextElem.appendChild( doc.createTextNode( (track->composer()) ) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "isrc" ); + cdTextElem.appendChild( doc.createTextNode( ( track->isrc()) ) ); + cdTextMain.appendChild( cdTextElem ); + + cdTextElem = doc.createElement( "message" ); + cdTextElem.appendChild( doc.createTextNode( (track->cdTextMessage()) ) ); + cdTextMain.appendChild( cdTextElem ); + + trackElem.appendChild( cdTextMain ); + + // add copy protection + QDomElement copyElem = doc.createElement( "copy_protection" ); + copyElem.appendChild( doc.createTextNode( track->copyProtection() ? "yes" : "no" ) ); + trackElem.appendChild( copyElem ); + + // add pre emphasis + copyElem = doc.createElement( "pre_emphasis" ); + copyElem.appendChild( doc.createTextNode( track->preEmp() ? "yes" : "no" ) ); + trackElem.appendChild( copyElem ); + + contentsElem.appendChild( trackElem ); + } + // ------------------------------------------------------------- + + docElem->appendChild( contentsElem ); + + return true; +} + + +int K3bAudioDoc::numOfTracks() const +{ + return ( m_lastTrack ? m_lastTrack->trackNumber() : 0 ); +} + + +K3bBurnJob* K3bAudioDoc::newBurnJob( K3bJobHandler* hdl, QObject* parent ) +{ + return new K3bAudioJob( this, hdl, parent ); +} + + +void K3bAudioDoc::informAboutNotFoundFiles() +{ + if( !m_notFoundFiles.isEmpty() ) { + QStringList l; + for( KURL::List::const_iterator it = m_notFoundFiles.begin(); + it != m_notFoundFiles.end(); ++it ) + l.append( (*it).path() ); + KMessageBox::informationList( qApp->activeWindow(), + i18n("Could not find the following files:"), + l, + i18n("Not Found") ); + + m_notFoundFiles.clear(); + } + if( !m_unknownFileFormatFiles.isEmpty() ) { + QStringList l; + for( KURL::List::const_iterator it = m_unknownFileFormatFiles.begin(); + it != m_unknownFileFormatFiles.end(); ++it ) + l.append( (*it).path() ); + KMessageBox::informationList( qApp->activeWindow(), + i18n("

Unable to handle the following files due to an unsupported format:" + "

You may manually convert these audio files to wave using another " + "application supporting the audio format and then add the wave files " + "to the K3b project."), + l, + i18n("Unsupported Format") ); + + m_unknownFileFormatFiles.clear(); + } +} + + + +void K3bAudioDoc::removeCorruptTracks() +{ +// K3bAudioTrack* track = m_tracks->first(); +// while( track ) { +// if( track->status() != 0 ) { +// removeTrack(track); +// track = m_tracks->current(); +// } +// else +// track = m_tracks->next(); +// } +} + + +void K3bAudioDoc::slotTrackChanged( K3bAudioTrack* track ) +{ + kdDebug() << "(K3bAudioDoc::slotTrackChanged " << track << endl; + setModified( true ); + // if the track is empty now we simply delete it + if( track->firstSource() ) { + emit trackChanged(track); + emit changed(); + } + else { + kdDebug() << "(K3bAudioDoc::slotTrackChanged) track " << track << " empty. Deleting." << endl; + delete track; // this will emit the proper signal + } + kdDebug() << "(K3bAudioDoc::slotTrackChanged done" << track << endl; +} + + +void K3bAudioDoc::slotTrackRemoved( K3bAudioTrack* track ) +{ + setModified( true ); + emit trackRemoved(track); + emit changed(); +} + + +void K3bAudioDoc::increaseDecoderUsage( K3bAudioDecoder* decoder ) +{ + kdDebug() << "(K3bAudioDoc::increaseDecoderUsage)" << endl; + if( !m_decoderUsageCounterMap.contains( decoder ) ) { + m_decoderUsageCounterMap[decoder] = 1; + m_decoderPresenceMap[decoder->filename()] = decoder; + } + else + m_decoderUsageCounterMap[decoder]++; + kdDebug() << "(K3bAudioDoc::increaseDecoderUsage) finished" << endl; +} + + +void K3bAudioDoc::decreaseDecoderUsage( K3bAudioDecoder* decoder ) +{ + m_decoderUsageCounterMap[decoder]--; + if( m_decoderUsageCounterMap[decoder] <= 0 ) { + m_decoderUsageCounterMap.erase(decoder); + m_decoderPresenceMap.erase(decoder->filename()); + delete decoder; + } +} + + +K3bDevice::CdText K3bAudioDoc::cdTextData() const +{ + K3bDevice::CdText text( m_cdTextData ); + text.reserve( numOfTracks() ); + K3bAudioTrack* track = firstTrack(); + while( track ) { + text.append( track->cdText() ); + + track = track->next(); + } + return text; +} + + +K3bDevice::Toc K3bAudioDoc::toToc() const +{ + K3bDevice::Toc toc; + + // FIXME: add MCN + + K3bAudioTrack* track = firstTrack(); + K3b::Msf pos = 0; + while( track ) { + toc.append( track->toCdTrack() ); + track = track->next(); + } + + return toc; +} + + +void K3bAudioDoc::setTitle( const QString& v ) +{ + m_cdTextData.setTitle( v ); + emit changed(); +} + + +void K3bAudioDoc::setArtist( const QString& v ) +{ + setPerformer( v ); +} + + +void K3bAudioDoc::setPerformer( const QString& v ) +{ + QString s( v ); + d->cdTextValidator->fixup( s ); + m_cdTextData.setPerformer( s ); + emit changed(); +} + + +void K3bAudioDoc::setDisc_id( const QString& v ) +{ + QString s( v ); + d->cdTextValidator->fixup( s ); + m_cdTextData.setDiscId( s ); + emit changed(); +} + + +void K3bAudioDoc::setArranger( const QString& v ) +{ + QString s( v ); + d->cdTextValidator->fixup( s ); + m_cdTextData.setArranger( s ); + emit changed(); +} + + +void K3bAudioDoc::setSongwriter( const QString& v ) +{ + QString s( v ); + d->cdTextValidator->fixup( s ); + m_cdTextData.setSongwriter( s ); + emit changed(); +} + + +void K3bAudioDoc::setComposer( const QString& v ) +{ + QString s( v ); + d->cdTextValidator->fixup( s ); + m_cdTextData.setComposer( s ); + emit changed(); +} + + +void K3bAudioDoc::setUpc_ean( const QString& v ) +{ + QString s( v ); + d->cdTextValidator->fixup( s ); + m_cdTextData.setUpcEan( s ); + emit changed(); +} + + +void K3bAudioDoc::setCdTextMessage( const QString& v ) +{ + QString s( v ); + d->cdTextValidator->fixup( s ); + m_cdTextData.setMessage( s ); + emit changed(); +} + +#include "k3baudiodoc.moc" diff --git a/libk3b/projects/audiocd/k3baudiodoc.h b/libk3b/projects/audiocd/k3baudiodoc.h new file mode 100644 index 0000000..87a512e --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiodoc.h @@ -0,0 +1,263 @@ +/* + * + * $Id: k3baudiodoc.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BAUDIODOC_H +#define K3BAUDIODOC_H + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "k3b_export.h" +#include + +class K3bApp; +class K3bAudioTrack; +class QWidget; +class QTimer; +class QDomDocument; +class QDomElement; +class K3bThreadJob; +class KConfig; +class K3bAudioDataSource; +class K3bAudioDecoder; +class K3bAudioFile; + +/**Document class for an audio project. + *@author Sebastian Trueg + */ + +class LIBK3B_EXPORT K3bAudioDoc : public K3bDoc +{ + Q_OBJECT + + friend class K3bMixedDoc; + friend class K3bAudioTrack; + friend class K3bAudioFile; + + public: + K3bAudioDoc( QObject* ); + ~K3bAudioDoc(); + + QString name() const; + + bool newDocument(); + + bool hideFirstTrack() const { return m_hideFirstTrack; } + int numOfTracks() const; + + bool normalize() const { return m_normalize; } + + K3bAudioTrack* firstTrack() const; + K3bAudioTrack* lastTrack() const; + + /** + * Slow. + * \return the K3bAudioTrack with track number trackNum starting at 1 or 0 if trackNum > numOfTracks() + */ + K3bAudioTrack* getTrack( unsigned int trackNum ); + + /** + * Creates a new audiofile inside this doc which has no track yet. + */ + K3bAudioFile* createAudioFile( const KURL& url ); + + /** get the current size of the project */ + KIO::filesize_t size() const; + K3b::Msf length() const; + + // CD-Text + bool cdText() const { return m_cdText; } + const QString& title() const { return m_cdTextData.title(); } + const QString& artist() const { return m_cdTextData.performer(); } + const QString& disc_id() const { return m_cdTextData.discId(); } + const QString& arranger() const { return m_cdTextData.arranger(); } + const QString& songwriter() const { return m_cdTextData.songwriter(); } + const QString& composer() const { return m_cdTextData.composer(); } + const QString& upc_ean() const { return m_cdTextData.upcEan(); } + const QString& cdTextMessage() const { return m_cdTextData.message(); } + + /** + * Create complete CD-Text including the tracks' data. + */ + K3bDevice::CdText cdTextData() const; + + int audioRippingParanoiaMode() const { return m_audioRippingParanoiaMode; } + int audioRippingRetries() const { return m_audioRippingRetries; } + bool audioRippingIgnoreReadErrors() const { return m_audioRippingIgnoreReadErrors; } + + /** + * Represent the structure of the doc as CD Table of Contents. + */ + K3bDevice::Toc toToc() const; + + K3bBurnJob* newBurnJob( K3bJobHandler*, QObject* parent = 0 ); + + /** + * Shows dialogs. + */ + void informAboutNotFoundFiles(); + + /** + * returns the new after track, ie. the the last added track or null if + * the import failed. + * + * This is a blocking method. + * + * \param cuefile The Cuefile to be imported + * \param after The track after which the new tracks should be inserted + * \param decoder The decoder to be used for the new tracks. If 0 a new one will be created. + * + * BE AWARE THAT THE DECODER HAS TO FIT THE AUDIO FILE IN THE CUE. + */ + K3bAudioTrack* importCueFile( const QString& cuefile, K3bAudioTrack* after, K3bAudioDecoder* decoder = 0 ); + + /** + * Create a decoder for a specific url. If another AudioFileSource with this + * url is already part of this project the associated decoder is returned. + * + * In the first case the decoder will not be initialized yet (K3bAudioDecoder::analyseFile + * is not called yet). + * + * \param url The url for which a decoder is requested. + * \param reused If not null this variable is set to true if the decoder is already in + * use and K3bAudioDecoder::analyseFile() does not have to be called anymore. + */ + K3bAudioDecoder* getDecoderForUrl( const KURL& url, bool* reused = 0 ); + + static bool readPlaylistFile( const KURL& url, KURL::List& playlist ); + + public slots: + void addUrls( const KURL::List& ); + void addTrack( const KURL&, uint ); + void addTracks( const KURL::List&, uint ); + /** + * Adds a track without any testing + * + * Slow because it uses getTrack. + */ + void addTrack( K3bAudioTrack* track, uint position = 0 ); + + void addSources( K3bAudioTrack* parent, const KURL::List& urls, K3bAudioDataSource* sourceAfter = 0 ); + + void removeTrack( K3bAudioTrack* ); + void moveTrack( K3bAudioTrack* track, K3bAudioTrack* after ); + + void setHideFirstTrack( bool b ) { m_hideFirstTrack = b; } + void setNormalize( bool b ) { m_normalize = b; } + + // CD-Text + void writeCdText( bool b ) { m_cdText = b; } + void setTitle( const QString& v ); + void setArtist( const QString& v ); + void setPerformer( const QString& v ); + void setDisc_id( const QString& v ); + void setArranger( const QString& v ); + void setSongwriter( const QString& v ); + void setComposer( const QString& v ); + void setUpc_ean( const QString& v ); + void setCdTextMessage( const QString& v ); + + // Audio-CD Ripping + void setAudioRippingParanoiaMode( int i ) { m_audioRippingParanoiaMode = i; } + void setAudioRippingRetries( int r ) { m_audioRippingRetries = r; } + void setAudioRippingIgnoreReadErrors( bool b ) { m_audioRippingIgnoreReadErrors = b; } + + void removeCorruptTracks(); + + private slots: + void slotTrackChanged( K3bAudioTrack* ); + void slotTrackRemoved( K3bAudioTrack* ); + + signals: + void trackChanged( K3bAudioTrack* ); + void trackRemoved( K3bAudioTrack* ); + + protected: + /** reimplemented from K3bDoc */ + bool loadDocumentData( QDomElement* ); + /** reimplemented from K3bDoc */ + bool saveDocumentData( QDomElement* ); + + QString typeString() const; + + private: + // the stuff for adding files + // --------------------------------------------------------- + K3bAudioTrack* createTrack( const KURL& url ); + + /** + * Handle directories and M3u files + */ + KURL::List extractUrlList( const KURL::List& urls ); + // --------------------------------------------------------- + + /** + * Used by K3bAudioTrack to update the track list + */ + void setFirstTrack( K3bAudioTrack* track ); + /** + * Used by K3bAudioTrack to update the track list + */ + void setLastTrack( K3bAudioTrack* track ); + + /** + * Used by K3bAudioFile to tell the doc that it does not need the decoder anymore. + */ + void decreaseDecoderUsage( K3bAudioDecoder* ); + void increaseDecoderUsage( K3bAudioDecoder* ); + + K3bAudioTrack* m_firstTrack; + K3bAudioTrack* m_lastTrack; + + bool m_hideFirstTrack; + bool m_normalize; + + KURL::List m_notFoundFiles; + KURL::List m_unknownFileFormatFiles; + + // CD-Text + // -------------------------------------------------- + K3bDevice::CdText m_cdTextData; + bool m_cdText; + // -------------------------------------------------- + + // Audio ripping + int m_audioRippingParanoiaMode; + int m_audioRippingRetries; + bool m_audioRippingIgnoreReadErrors; + + // + // decoder housekeeping + // -------------------------------------------------- + // used to check if we may delete a decoder + QMap m_decoderUsageCounterMap; + // used to check if we already have a decoder for a specific file + QMap m_decoderPresenceMap; + + class Private; + Private* d; +}; + + +#endif diff --git a/libk3b/projects/audiocd/k3baudiofile.cpp b/libk3b/projects/audiocd/k3baudiofile.cpp new file mode 100644 index 0000000..2011e73 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiofile.cpp @@ -0,0 +1,112 @@ +/* + * + * $Id: k3baudiofile.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudiofile.h" +#include "k3baudiodoc.h" +#include "k3baudiotrack.h" + +#include + + +K3bAudioFile::K3bAudioFile( K3bAudioDecoder* dec, K3bAudioDoc* doc ) + : K3bAudioDataSource(), + m_doc(doc), + m_decoder(dec), + m_decodedData(0) +{ + // FIXME: somehow make it possible to switch docs + doc->increaseDecoderUsage( m_decoder ); +} + + +K3bAudioFile::K3bAudioFile( const K3bAudioFile& file ) + : K3bAudioDataSource( file ), + m_doc( file.m_doc ), + m_decoder( file.m_decoder ), + m_decodedData(0) +{ + m_doc->increaseDecoderUsage( m_decoder ); +} + + +K3bAudioFile::~K3bAudioFile() +{ + m_doc->decreaseDecoderUsage( m_decoder ); +} + + +QString K3bAudioFile::type() const +{ + return m_decoder->fileType(); +} + + +QString K3bAudioFile::sourceComment() const +{ + return m_decoder->filename().section( "/", -1 ); +} + + +const QString& K3bAudioFile::filename() const +{ + return m_decoder->filename(); +} + + +bool K3bAudioFile::isValid() const +{ + return m_decoder->isValid(); +} + + +K3b::Msf K3bAudioFile::originalLength() const +{ + return m_decoder->length(); +} + + +bool K3bAudioFile::seek( const K3b::Msf& msf ) +{ + // this is valid once the decoder has been initialized. + if( startOffset() + msf <= lastSector() && + m_decoder->seek( startOffset() + msf ) ) { + m_decodedData = msf.audioBytes(); + return true; + } + else + return false; +} + + +int K3bAudioFile::read( char* data, unsigned int max ) +{ + // here we can trust on the decoder to always provide enough data + // see if we decode too much + if( max + m_decodedData > length().audioBytes() ) + max = length().audioBytes() - m_decodedData; + + int read = m_decoder->decode( data, max ); + + if( read > 0 ) + m_decodedData += read; + + return read; +} + + +K3bAudioDataSource* K3bAudioFile::copy() const +{ + return new K3bAudioFile( *this ); +} diff --git a/libk3b/projects/audiocd/k3baudiofile.h b/libk3b/projects/audiocd/k3baudiofile.h new file mode 100644 index 0000000..83f75eb --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiofile.h @@ -0,0 +1,85 @@ +/* + * + * $Id: k3baudiofile.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_FILE_H_ +#define _K3B_AUDIO_FILE_H_ + +#include "k3baudiodatasource.h" + +#include +#include +#include "k3b_export.h" + +class K3bAudioDecoder; +class K3bAudioTrack; + + +/** + * The K3bAudioFile is the most important audio data source. It gets its data + * from an audio file and uses a K3bAudioDecoder to decode this data. + * + * Be aware that it is currently not possible to change the doc of an AudioFile. + * The reason for this is the decoder sharing which is in place to allow gapless + * splitting of audio files into several tracks. + * + * \see K3bAudioDoc::createDecoderForUrl + */ +class LIBK3B_EXPORT K3bAudioFile : public K3bAudioDataSource +{ + public: + /** + * The AudioFile registers itself with the doc. This is part of the + * decoder handling facility in K3bAudioDoc which reuses the same decoder + * for sources with the same url. + * + * Use K3bAudioDoc::getDecoderForUrl to create a decoder. + */ + K3bAudioFile( K3bAudioDecoder*, K3bAudioDoc* ); + K3bAudioFile( const K3bAudioFile& ); + + /** + * The AudioFile deregisters itself from the doc. If it was the last file + * to use the decoder the doc will take care of deleting it. + */ + ~K3bAudioFile(); + + const QString& filename() const; + + /** + * The complete length of the file used by this source. + */ + K3b::Msf originalLength() const; + + QString type() const; + QString sourceComment() const; + + bool isValid() const; + + K3bAudioDecoder* decoder() const { return m_decoder; } + + bool seek( const K3b::Msf& ); + + int read( char* data, unsigned int max ); + + K3bAudioDataSource* copy() const; + + private: + K3bAudioDoc* m_doc; + K3bAudioDecoder* m_decoder; + + unsigned long long m_decodedData; +}; + +#endif diff --git a/libk3b/projects/audiocd/k3baudioimager.cpp b/libk3b/projects/audiocd/k3baudioimager.cpp new file mode 100644 index 0000000..b8a7a11 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudioimager.cpp @@ -0,0 +1,203 @@ +/* + * + * $Id: k3baudioimager.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudioimager.h" +#include "k3baudiodoc.h" +#include "k3baudiotrack.h" +#include "k3baudiodatasource.h" + +#include +#include + +#include +#include + +#include + +#include + + +class K3bAudioImager::WorkThread : public K3bThread +{ +public: + WorkThread( K3bAudioDoc* doc ); + + void run(); + + void cancel(); + + bool m_canceled; + int m_fd; + QStringList m_imageNames; + K3bAudioImager::ErrorType lastError; + +private: + K3bAudioDoc* m_doc; +}; + + +K3bAudioImager::WorkThread::WorkThread( K3bAudioDoc* doc ) + : K3bThread(), + m_canceled(false), + m_fd(-1), + m_doc(doc) +{ +} + + +void K3bAudioImager::WorkThread::run() +{ + m_canceled = false; + + emitStarted(); + + lastError = K3bAudioImager::ERROR_UNKNOWN; + + // + // + // + QStringList::iterator imageFileIt = m_imageNames.begin(); + K3bWaveFileWriter waveFileWriter; + + K3bAudioTrack* track = m_doc->firstTrack(); + int trackNumber = 1; + unsigned long long totalSize = m_doc->length().audioBytes(); + unsigned long long totalRead = 0; + char buffer[2352 * 10]; + + while( track ) { + + emitNextTrack( trackNumber, m_doc->numOfTracks() ); + + // + // Seek to the beginning of the track + // + if( !track->seek(0) ) { + emitInfoMessage( i18n("Unable to seek in track %1.").arg(trackNumber), K3bJob::ERROR ); + emitFinished(false); + return; + } + + // + // Initialize the reading + // + int read = 0; + unsigned long long trackRead = 0; + + // + // Create the image file + // + if( m_fd == -1 ) { + if( !waveFileWriter.open( *imageFileIt ) ) { + emitInfoMessage( i18n("Could not open %1 for writing").arg(*imageFileIt), K3bJob::ERROR ); + emitFinished(false); + return; + } + } + + // + // Read data from the track + // + while( (read = track->read( buffer, sizeof(buffer) )) > 0 ) { + if( m_fd == -1 ) { + waveFileWriter.write( buffer, read, K3bWaveFileWriter::BigEndian ); + } + else { + if( ::write( m_fd, reinterpret_cast(buffer), read ) != read ) { + kdDebug() << "(K3bAudioImager::WorkThread) writing to fd " << m_fd << " failed." << endl; + lastError = K3bAudioImager::ERROR_FD_WRITE; + emitFinished(false); + return; + } + } + + if( m_canceled ) { + emitCanceled(); + emitFinished(false); + return; + } + + // + // Emit progress + // + totalRead += read; + trackRead += read; + + emitSubPercent( 100*trackRead/track->length().audioBytes() ); + emitPercent( 100*totalRead/totalSize ); + emitProcessedSubSize( trackRead/1024/1024, track->length().audioBytes()/1024/1024 ); + emitProcessedSize( totalRead/1024/1024, totalSize/1024/1024 ); + } + + if( read < 0 ) { + emitInfoMessage( i18n("Error while decoding track %1.").arg(trackNumber), K3bJob::ERROR ); + kdDebug() << "(K3bAudioImager::WorkThread) read error on track " << trackNumber + << " at pos " << K3b::Msf(trackRead/2352) << endl; + lastError = K3bAudioImager::ERROR_DECODING_TRACK; + emitFinished(false); + return; + } + + track = track->next(); + trackNumber++; + imageFileIt++; + } + + emitFinished(true); +} + + +void K3bAudioImager::WorkThread::cancel() +{ + m_canceled = true; +} + + + + +K3bAudioImager::K3bAudioImager( K3bAudioDoc* doc, K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bThreadJob( jh, parent, name ), + m_doc(doc) +{ + m_thread = new WorkThread(doc); + setThread( m_thread ); +} + + +K3bAudioImager::~K3bAudioImager() +{ + delete m_thread; +} + + +void K3bAudioImager::writeToFd( int fd ) +{ + m_thread->m_fd = fd; +} + + +void K3bAudioImager::setImageFilenames( const QStringList& p ) +{ + m_thread->m_imageNames = p; + m_thread->m_fd = -1; +} + + +K3bAudioImager::ErrorType K3bAudioImager::lastErrorType() const +{ + return m_thread->lastError; +} + +#include "k3baudioimager.moc" diff --git a/libk3b/projects/audiocd/k3baudioimager.h b/libk3b/projects/audiocd/k3baudioimager.h new file mode 100644 index 0000000..df4ae7a --- /dev/null +++ b/libk3b/projects/audiocd/k3baudioimager.h @@ -0,0 +1,59 @@ +/* + * + * $Id: k3baudioimager.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_IMAGER_H_ +#define _K3B_AUDIO_IMAGER_H_ + +#include + +class K3bAudioDoc; + +class K3bAudioImager : public K3bThreadJob +{ + Q_OBJECT + + public: + K3bAudioImager( K3bAudioDoc*, K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bAudioImager(); + + /** + * the data gets written directly into fd instead of the imagefile. + * Be aware that this only makes sense before starting the job. + * To disable just set fd to -1 + */ + void writeToFd( int fd ); + + /** + * Image path. Should be an empty directory or a non-existing + * directory in which case it will be created. + */ + void setImageFilenames( const QStringList& p ); + + enum ErrorType { + ERROR_FD_WRITE, + ERROR_DECODING_TRACK, + ERROR_UNKNOWN + }; + + ErrorType lastErrorType() const; + + private: + K3bAudioDoc* m_doc; + + class WorkThread; + WorkThread* m_thread; +}; + +#endif diff --git a/libk3b/projects/audiocd/k3baudiojob.cpp b/libk3b/projects/audiocd/k3baudiojob.cpp new file mode 100644 index 0000000..c2e62c2 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiojob.cpp @@ -0,0 +1,864 @@ +/* + * + * $Id: k3baudiojob.cpp 690212 2007-07-20 11:02:13Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3baudiojob.h" + +#include "k3baudioimager.h" +#include +#include "k3baudiotrack.h" +#include "k3baudiodatasource.h" +#include "k3baudionormalizejob.h" +#include "k3baudiojobtempdata.h" +#include "k3baudiomaxspeedjob.h" +#include "k3baudiocdtracksource.h" +#include "k3baudiofile.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + + +static QString createNonExistingFilesString( const QValueList& items, unsigned int max ) +{ + QString s; + unsigned int cnt = 0; + for( QValueList::const_iterator it = items.begin(); + it != items.end(); ++it ) { + + s += KStringHandler::csqueeze( (*it)->filename(), 60 ); + + ++cnt; + if( cnt >= max || it == items.end() ) + break; + + s += "
"; + } + + if( items.count() > max ) + s += "..."; + + return s; +} + + + +class K3bAudioJob::Private +{ + public: + Private() + : copies(1), + copiesDone(0) { + } + + int copies; + int copiesDone; + int usedSpeed; + + bool useCdText; + bool maxSpeed; + + bool zeroPregap; + bool less4Sec; +}; + + +K3bAudioJob::K3bAudioJob( K3bAudioDoc* doc, K3bJobHandler* hdl, QObject* parent ) + : K3bBurnJob( hdl, parent ), + m_doc( doc ), + m_normalizeJob(0), + m_maxSpeedJob(0) +{ + d = new Private; + + m_audioImager = new K3bAudioImager( m_doc, this, this ); + connect( m_audioImager, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_audioImager, SIGNAL(percent(int)), + this, SLOT(slotAudioDecoderPercent(int)) ); + connect( m_audioImager, SIGNAL(subPercent(int)), + this, SLOT(slotAudioDecoderSubPercent(int)) ); + connect( m_audioImager, SIGNAL(finished(bool)), + this, SLOT(slotAudioDecoderFinished(bool)) ); + connect( m_audioImager, SIGNAL(nextTrack(int, int)), + this, SLOT(slotAudioDecoderNextTrack(int, int)) ); + + m_writer = 0; + m_tempData = new K3bAudioJobTempData( m_doc, this ); +} + + +K3bAudioJob::~K3bAudioJob() +{ + delete d; +} + + +K3bDevice::Device* K3bAudioJob::writer() const +{ + if( m_doc->onlyCreateImages() ) + return 0; // no writer needed -> no blocking on K3bBurnJob + else + return m_doc->burner(); +} + + +K3bDoc* K3bAudioJob::doc() const +{ + return m_doc; +} + + +void K3bAudioJob::start() +{ + jobStarted(); + + m_written = true; + m_canceled = false; + m_errorOccuredAndAlreadyReported = false; + d->copies = m_doc->copies(); + d->copiesDone = 0; + d->useCdText = m_doc->cdText(); + d->usedSpeed = m_doc->speed(); + d->maxSpeed = false; + + if( m_doc->dummy() ) + d->copies = 1; + + emit newTask( i18n("Preparing data") ); + + // + // Check if all files exist + // + QValueList nonExistingFiles; + K3bAudioTrack* track = m_doc->firstTrack(); + while( track ) { + K3bAudioDataSource* source = track->firstSource(); + while( source ) { + if( K3bAudioFile* file = dynamic_cast( source ) ) { + if( !QFile::exists( file->filename() ) ) + nonExistingFiles.append( file ); + } + source = source->next(); + } + track = track->next(); + } + if( !nonExistingFiles.isEmpty() ) { + if( questionYesNo( "

" + i18n("The following files could not be found. Do you want to remove them from the " + "project and continue without adding them to the image?") + + "

" + createNonExistingFilesString( nonExistingFiles, 10 ), + i18n("Warning"), + i18n("Remove missing files and continue"), + i18n("Cancel and go back") ) ) { + for( QValueList::const_iterator it = nonExistingFiles.begin(); + it != nonExistingFiles.end(); ++it ) { + delete *it; + } + } + else { + m_canceled = true; + emit canceled(); + jobFinished(false); + return; + } + } + + // + // Make sure the project is not empty + // + if( m_doc->numOfTracks() == 0 ) { + emit infoMessage( i18n("Please add files to your project first."), ERROR ); + jobFinished(false); + return; + } + + if( m_doc->onTheFly() && !checkAudioSources() ) { + emit infoMessage( i18n("Unable to write on-the-fly with these audio sources."), WARNING ); + m_doc->setOnTheFly(false); + } + + + // we don't need this when only creating image and it is possible + // that the burn device is null + if( !m_doc->onlyCreateImages() ) { + + // + // there are a lot of writers out there which produce coasters + // in dao mode if the CD contains pregaps of length 0 (or maybe already != 2 secs?) + // + // Also most writers do not accept cuesheets with tracks smaller than 4 seconds (a violation + // of the red book standard) in DAO mode. + // + d->zeroPregap = false; + d->less4Sec = false; + track = m_doc->firstTrack(); + while( track ) { + if( track->postGap() == 0 && track->next() != 0 ) // the last track's postgap is always 0 + d->zeroPregap = true; + + if( track->length() < K3b::Msf( 0, 4, 0 ) ) + d->less4Sec = true; + + track = track->next(); + } + + // determine writing mode + if( m_doc->writingMode() == K3b::WRITING_MODE_AUTO ) { + // + // DAO is always the first choice + // RAW second and TAO last + // there are none-DAO writers that are supported by cdrdao + // + // older cdrecord versions do not support the -shorttrack option in RAW writing mode + // + if( !writer()->dao() && writingApp() == K3b::CDRECORD ) { + if(!writer()->supportsRawWriting() && + ( !d->less4Sec || k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "short-track-raw" ) ) ) + m_usedWritingMode = K3b::RAW; + else + m_usedWritingMode = K3b::TAO; + } + else { + if( (d->zeroPregap||d->less4Sec) && writer()->supportsRawWriting() ) { + m_usedWritingMode = K3b::RAW; + if( d->less4Sec ) + emit infoMessage( i18n("Tracklengths below 4 seconds violate the Red Book standard."), WARNING ); + } + else + m_usedWritingMode = K3b::DAO; + } + } + else + m_usedWritingMode = m_doc->writingMode(); + + bool cdrecordOnTheFly = false; + bool cdrecordCdText = false; + if( k3bcore->externalBinManager()->binObject("cdrecord") ) { + cdrecordOnTheFly = k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "audio-stdin" ); + cdrecordCdText = k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "cdtext" ); + } + + // determine writing app + if( writingApp() == K3b::DEFAULT ) { + if( m_usedWritingMode == K3b::DAO ) { + // there are none-DAO writers that are supported by cdrdao + if( !writer()->dao() || + ( !cdrecordOnTheFly && m_doc->onTheFly() ) || + ( d->useCdText && !cdrecordCdText ) || + m_doc->hideFirstTrack() ) + m_usedWritingApp = K3b::CDRDAO; + else + m_usedWritingApp = K3b::CDRECORD; + } + else + m_usedWritingApp = K3b::CDRECORD; + } + else + m_usedWritingApp = writingApp(); + + // on-the-fly writing with cdrecord >= 2.01a13 + if( m_usedWritingApp == K3b::CDRECORD && + m_doc->onTheFly() && + !cdrecordOnTheFly ) { + emit infoMessage( i18n("On-the-fly writing with cdrecord < 2.01a13 not supported."), ERROR ); + m_doc->setOnTheFly(false); + } + + if( m_usedWritingApp == K3b::CDRECORD && + d->useCdText ) { + if( !cdrecordCdText ) { + emit infoMessage( i18n("Cdrecord %1 does not support CD-Text writing.") + .arg(k3bcore->externalBinManager()->binObject("cdrecord")->version), ERROR ); + d->useCdText = false; + } + else if( m_usedWritingMode == K3b::TAO ) { + emit infoMessage( i18n("It is not possible to write CD-Text in TAO mode."), WARNING ); + d->useCdText = false; + } + } + } + + + if( !m_doc->onlyCreateImages() && m_doc->onTheFly() ) { + if( m_doc->speed() == 0 ) { + // try to determine the max possible speed + emit newSubTask( i18n("Determining maximum writing speed") ); + if( !m_maxSpeedJob ) { + m_maxSpeedJob = new K3bAudioMaxSpeedJob( m_doc, this, this ); + connect( m_maxSpeedJob, SIGNAL(percent(int)), + this, SIGNAL(subPercent(int)) ); + connect( m_maxSpeedJob, SIGNAL(finished(bool)), + this, SLOT(slotMaxSpeedJobFinished(bool)) ); + } + m_maxSpeedJob->start(); + return; + } + else { + if( !prepareWriter() ) { + cleanupAfterError(); + jobFinished(false); + return; + } + + if( startWriting() ) { + + // now the writer is running and we can get it's stdin + // we only use this method when writing on-the-fly since + // we cannot easily change the audioDecode fd while it's working + // which we would need to do since we write into several + // image files. + m_audioImager->writeToFd( m_writer->fd() ); + } + else { + // startWriting() already did the cleanup + return; + } + } + } + else { + emit burning(false); + emit infoMessage( i18n("Creating image files in %1").arg(m_doc->tempDir()), INFO ); + emit newTask( i18n("Creating image files") ); + m_tempData->prepareTempFileNames( doc()->tempDir() ); + QStringList filenames; + for( int i = 1; i <= m_doc->numOfTracks(); ++i ) + filenames += m_tempData->bufferFileName( i ); + m_audioImager->setImageFilenames( filenames ); + } + + m_audioImager->start(); +} + + +void K3bAudioJob::slotMaxSpeedJobFinished( bool success ) +{ + d->maxSpeed = success; + if( !success ) + emit infoMessage( i18n("Unable to determine maximum speed for some reason. Ignoring."), WARNING ); + + // now start the writing + // same code as above. See the commecnts there + if( !prepareWriter() ) { + cleanupAfterError(); + jobFinished(false); + return; + } + + if( startWriting() ) + m_audioImager->writeToFd( m_writer->fd() ); + + m_audioImager->start(); +} + + +void K3bAudioJob::cancel() +{ + m_canceled = true; + + if( m_maxSpeedJob ) + m_maxSpeedJob->cancel(); + + if( m_writer ) + m_writer->cancel(); + + m_audioImager->cancel(); + emit infoMessage( i18n("Writing canceled."), K3bJob::ERROR ); + removeBufferFiles(); + emit canceled(); + jobFinished(false); +} + + +void K3bAudioJob::slotWriterFinished( bool success ) +{ + if( m_canceled || m_errorOccuredAndAlreadyReported ) + return; + + if( !success ) { + cleanupAfterError(); + jobFinished(false); + return; + } + else { + d->copiesDone++; + + if( d->copiesDone == d->copies ) { + if( m_doc->onTheFly() || m_doc->removeImages() ) + removeBufferFiles(); + + jobFinished(true); + } + else { + K3bDevice::eject( m_doc->burner() ); + + if( startWriting() ) { + if( m_doc->onTheFly() ) { + // now the writer is running and we can get it's stdin + // we only use this method when writing on-the-fly since + // we cannot easily change the audioDecode fd while it's working + // which we would need to do since we write into several + // image files. + m_audioImager->writeToFd( m_writer->fd() ); + m_audioImager->start(); + } + } + } + } +} + + +void K3bAudioJob::slotAudioDecoderFinished( bool success ) +{ + if( m_canceled || m_errorOccuredAndAlreadyReported ) + return; + + if( !success ) { + if( m_audioImager->lastErrorType() == K3bAudioImager::ERROR_FD_WRITE ) { + // this means that the writer job failed so let's use the error handling there. + return; + } + + emit infoMessage( i18n("Error while decoding audio tracks."), ERROR ); + cleanupAfterError(); + jobFinished(false); + return; + } + + if( m_doc->onlyCreateImages() || !m_doc->onTheFly() ) { + + emit infoMessage( i18n("Successfully decoded all tracks."), SUCCESS ); + + if( m_doc->normalize() ) { + normalizeFiles(); + } + else if( !m_doc->onlyCreateImages() ) { + if( !prepareWriter() ) { + cleanupAfterError(); + jobFinished(false); + } + else + startWriting(); + } + else { + jobFinished(true); + } + } +} + + +void K3bAudioJob::slotAudioDecoderNextTrack( int t, int tt ) +{ + if( m_doc->onlyCreateImages() || !m_doc->onTheFly() ) { + K3bAudioTrack* track = m_doc->getTrack(t); + emit newSubTask( i18n("Decoding audio track %1 of %2%3") + .arg(t) + .arg(tt) + .arg( track->title().isEmpty() || track->artist().isEmpty() + ? QString::null + : " (" + track->artist() + " - " + track->title() + ")" ) ); + } +} + + +bool K3bAudioJob::prepareWriter() +{ + delete m_writer; + + if( m_usedWritingApp == K3b::CDRECORD ) { + + if( !writeInfFiles() ) { + kdDebug() << "(K3bAudioJob) could not write inf-files." << endl; + emit infoMessage( i18n("IO Error. Most likely no space left on harddisk."), ERROR ); + + return false; + } + + K3bCdrecordWriter* writer = new K3bCdrecordWriter( m_doc->burner(), this, this ); + + writer->setWritingMode( m_usedWritingMode ); + writer->setSimulate( m_doc->dummy() ); + writer->setBurnSpeed( d->usedSpeed ); + + writer->addArgument( "-useinfo" ); + + if( d->useCdText ) { + writer->setRawCdText( m_doc->cdTextData().rawPackData() ); + } + + // add all the audio tracks + writer->addArgument( "-audio" ); + + // we only need to pad in one case. cdrecord < 2.01.01a03 cannot handle shorttrack + raw + if( d->less4Sec ) { + if( m_usedWritingMode == K3b::RAW && + !k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "short-track-raw" ) ) { + writer->addArgument( "-pad" ); + } + else { + // Allow tracks shorter than 4 seconds + writer->addArgument( "-shorttrack" ); + } + } + + K3bAudioTrack* track = m_doc->firstTrack(); + while( track ) { + if( m_doc->onTheFly() ) { + // this is only supported by cdrecord versions >= 2.01a13 + writer->addArgument( QFile::encodeName( m_tempData->infFileName( track ) ) ); + } + else { + writer->addArgument( QFile::encodeName( m_tempData->bufferFileName( track ) ) ); + } + track = track->next(); + } + + m_writer = writer; + } + else { + if( !writeTocFile() ) { + kdDebug() << "(K3bDataJob) could not write tocfile." << endl; + emit infoMessage( i18n("IO Error"), ERROR ); + + return false; + } + + // create the writer + // create cdrdao job + K3bCdrdaoWriter* writer = new K3bCdrdaoWriter( m_doc->burner(), this, this ); + writer->setCommand( K3bCdrdaoWriter::WRITE ); + writer->setSimulate( m_doc->dummy() ); + writer->setBurnSpeed( d->usedSpeed ); + writer->setTocFile( m_tempData->tocFileName() ); + + m_writer = writer; + } + + connect( m_writer, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_writer, SIGNAL(percent(int)), this, SLOT(slotWriterJobPercent(int)) ); + connect( m_writer, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSize(int, int)) ); + connect( m_writer, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); + connect( m_writer, SIGNAL(processedSubSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( m_writer, SIGNAL(nextTrack(int, int)), this, SLOT(slotWriterNextTrack(int, int)) ); + connect( m_writer, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) ); + connect( m_writer, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); + connect( m_writer, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + connect( m_writer, SIGNAL(finished(bool)), this, SLOT(slotWriterFinished(bool)) ); + // connect( m_writer, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) ); + connect( m_writer, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_writer, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + + return true; +} + + +void K3bAudioJob::slotWriterNextTrack( int t, int tt ) +{ + K3bAudioTrack* track = m_doc->getTrack(t); + // t is in range 1..tt + if( m_doc->hideFirstTrack() ) + track = m_doc->getTrack(t+1); + emit newSubTask( i18n("Writing track %1 of %2%3") + .arg(t) + .arg(tt) + .arg( track->title().isEmpty() || track->artist().isEmpty() + ? QString::null + : " (" + track->artist() + " - " + track->title() + ")" ) ); +} + + +void K3bAudioJob::slotWriterJobPercent( int p ) +{ + double totalTasks = d->copies; + double tasksDone = d->copiesDone; + if( m_doc->normalize() ) { + totalTasks+=1.0; + tasksDone+=1.0; + } + if( !m_doc->onTheFly() ) { + totalTasks+=1.0; + tasksDone+=1.0; + } + + emit percent( (int)((100.0*tasksDone + (double)p) / totalTasks) ); +} + + +void K3bAudioJob::slotAudioDecoderPercent( int p ) +{ + if( m_doc->onlyCreateImages() ) { + if( m_doc->normalize() ) + emit percent( p/2 ); + else + emit percent( p ); + } + else if( !m_doc->onTheFly() ) { + double totalTasks = d->copies; + double tasksDone = d->copiesDone; // =0 when creating an image + if( m_doc->normalize() ) { + totalTasks+=1.0; + } + if( !m_doc->onTheFly() ) { + totalTasks+=1.0; + } + + emit percent( (int)((100.0*tasksDone + (double)p) / totalTasks) ); + } +} + + +void K3bAudioJob::slotAudioDecoderSubPercent( int p ) +{ + // when writing on the fly the writer produces the subPercent + if( m_doc->onlyCreateImages() || !m_doc->onTheFly() ) { + emit subPercent( p ); + } +} + + +bool K3bAudioJob::startWriting() +{ + if( m_doc->dummy() ) + emit newTask( i18n("Simulating") ); + else if( d->copies > 1 ) + emit newTask( i18n("Writing Copy %1").arg(d->copiesDone+1) ); + else + emit newTask( i18n("Writing") ); + + + emit newSubTask( i18n("Waiting for media") ); + if( waitForMedia( m_doc->burner() ) < 0 ) { + cancel(); + return false; + } + + // just to be sure we did not get canceled during the async discWaiting + if( m_canceled ) + return false; + + // in case we determined the max possible writing speed we have to reset the speed on the writer job + // here since an inserted media is necessary + // the Max speed job will compare the max speed value with the supported values of the writer + if( d->maxSpeed ) + m_writer->setBurnSpeed( m_maxSpeedJob->maxSpeed() ); + + emit burning(true); + m_writer->start(); + return true; +} + + +void K3bAudioJob::cleanupAfterError() +{ + m_errorOccuredAndAlreadyReported = true; + m_audioImager->cancel(); + + if( m_writer ) + m_writer->cancel(); + + // remove the temp files + removeBufferFiles(); +} + + +void K3bAudioJob::removeBufferFiles() +{ + if ( !m_doc->onTheFly() ) { + emit infoMessage( i18n("Removing temporary files."), INFO ); + } + + // removes buffer images and temp toc or inf files + m_tempData->cleanup(); +} + + +void K3bAudioJob::normalizeFiles() +{ + if( !m_normalizeJob ) { + m_normalizeJob = new K3bAudioNormalizeJob( this, this ); + + connect( m_normalizeJob, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_normalizeJob, SIGNAL(percent(int)), this, SLOT(slotNormalizeProgress(int)) ); + connect( m_normalizeJob, SIGNAL(subPercent(int)), this, SLOT(slotNormalizeSubProgress(int)) ); + connect( m_normalizeJob, SIGNAL(finished(bool)), this, SLOT(slotNormalizeJobFinished(bool)) ); + connect( m_normalizeJob, SIGNAL(newTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_normalizeJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + } + + // add all the files + // TODO: we may need to split the wave files and put them back together! + QValueVector files; + K3bAudioTrack* track = m_doc->firstTrack(); + while( track ) { + files.append( m_tempData->bufferFileName(track) ); + track = track->next(); + } + + m_normalizeJob->setFilesToNormalize( files ); + + emit newTask( i18n("Normalizing volume levels") ); + m_normalizeJob->start(); +} + +void K3bAudioJob::slotNormalizeJobFinished( bool success ) +{ + if( m_canceled || m_errorOccuredAndAlreadyReported ) + return; + + if( success ) { + if( m_doc->onlyCreateImages() ) { + jobFinished(true); + } + else { + // start the writing + if( !prepareWriter() ) { + cleanupAfterError(); + jobFinished(false); + } + else + startWriting(); + } + } + else { + cleanupAfterError(); + jobFinished(false); + } +} + +void K3bAudioJob::slotNormalizeProgress( int p ) +{ + double totalTasks = d->copies+2.0; + double tasksDone = 1; // the decoding has been finished + + emit percent( (int)((100.0*tasksDone + (double)p) / totalTasks) ); +} + + +void K3bAudioJob::slotNormalizeSubProgress( int p ) +{ + emit subPercent( p ); +} + + +bool K3bAudioJob::writeTocFile() +{ + K3bTocFileWriter tocWriter; + tocWriter.setData( m_doc->toToc() ); + tocWriter.setHideFirstTrack( m_doc->hideFirstTrack() ); + if( d->useCdText ) + tocWriter.setCdText( m_doc->cdTextData() ); + if( !m_doc->onTheFly() ) { + QStringList filenames; + for( int i = 1; i <= m_doc->numOfTracks(); ++i ) + filenames += m_tempData->bufferFileName( i ); + tocWriter.setFilenames( filenames ); + } + return tocWriter.save( m_tempData->tocFileName() ); +} + + +bool K3bAudioJob::writeInfFiles() +{ + K3bInfFileWriter infFileWriter; + K3bAudioTrack* track = m_doc->firstTrack(); + while( track ) { + + infFileWriter.setTrack( track->toCdTrack() ); + infFileWriter.setTrackNumber( track->trackNumber() ); + if( !m_doc->onTheFly() ) + infFileWriter.setBigEndian( false ); + + if( !infFileWriter.save( m_tempData->infFileName(track) ) ) + return false; + + track = track->next(); + } + return true; +} + + +// checks if the doc contains sources from an audio cd which cannot be read on-the-fly +bool K3bAudioJob::checkAudioSources() +{ + K3bAudioTrack* track = m_doc->firstTrack(); + K3bAudioDataSource* source = track->firstSource(); + + while( source ) { + + if( K3bAudioCdTrackSource* cdSource = dynamic_cast(source) ) { + // + // If which cases we cannot wite on-the-fly: + // 1. the writing device contains one of the audio cds + // 2. Well, one of the cds is missing + // + K3bDevice::Device* dev = cdSource->searchForAudioCD(); + if( !dev || dev == writer() ) + return false; + else + cdSource->setDevice( dev ); + } + + // next source + source = source->next(); + if( !source ) { + track = track->next(); + if( track ) + source = track->firstSource(); + } + } + + return true; +} + + +QString K3bAudioJob::jobDescription() const +{ + return i18n("Writing Audio CD") + + ( m_doc->title().isEmpty() + ? QString::null + : QString( " (%1)" ).arg(m_doc->title()) ); +} + + +QString K3bAudioJob::jobDetails() const +{ + return ( i18n( "1 track (%1 minutes)", + "%n tracks (%1 minutes)", + m_doc->numOfTracks() ).arg(m_doc->length().toString()) + + ( m_doc->copies() > 1 && !m_doc->dummy() + ? i18n(" - %n copy", " - %n copies", m_doc->copies()) + : QString::null ) ); +} + +#include "k3baudiojob.moc" diff --git a/libk3b/projects/audiocd/k3baudiojob.h b/libk3b/projects/audiocd/k3baudiojob.h new file mode 100644 index 0000000..af37639 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiojob.h @@ -0,0 +1,107 @@ +/* + * + * $Id: k3baudiojob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BAUDIOJOB_H +#define K3BAUDIOJOB_H + +#include + + +class K3bAudioDoc; +class K3bAudioImager; +class QFile; +class QDataStream; +class K3bAbstractWriter; +class KTempFile; +class K3bCdrecordWriter; +class K3bAudioNormalizeJob; +class K3bAudioJobTempData; +class K3bDevice::Device; +class K3bAudioMaxSpeedJob; + +/** + *@author Sebastian Trueg + */ +class K3bAudioJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bAudioJob( K3bAudioDoc*, K3bJobHandler*, QObject* parent = 0 ); + ~K3bAudioJob(); + + K3bDoc* doc() const; + K3bDevice::Device* writer() const; + + QString jobDescription() const; + QString jobDetails() const; + + public slots: + void cancel(); + void start(); + + protected slots: + // writer slots + void slotWriterFinished( bool success ); + void slotWriterNextTrack(int, int); + void slotWriterJobPercent(int); + + // audiodecoder slots + void slotAudioDecoderFinished( bool ); + void slotAudioDecoderNextTrack( int, int ); + void slotAudioDecoderPercent(int); + void slotAudioDecoderSubPercent( int ); + + // normalizing slots + void slotNormalizeJobFinished( bool ); + void slotNormalizeProgress( int ); + void slotNormalizeSubProgress( int ); + + // max speed + void slotMaxSpeedJobFinished( bool ); + + private: + bool prepareWriter(); + bool startWriting(); + void cleanupAfterError(); + void removeBufferFiles(); + void normalizeFiles(); + bool writeTocFile(); + bool writeInfFiles(); + bool checkAudioSources(); + + K3bAudioDoc* m_doc; + K3bAudioImager* m_audioImager; + K3bAbstractWriter* m_writer; + K3bAudioNormalizeJob* m_normalizeJob; + K3bAudioJobTempData* m_tempData; + K3bAudioMaxSpeedJob* m_maxSpeedJob; + + KTempFile* m_tocFile; + + bool m_canceled; + bool m_errorOccuredAndAlreadyReported; + + bool m_written; + + int m_usedWritingApp; + int m_usedWritingMode; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/audiocd/k3baudiojobtempdata.cpp b/libk3b/projects/audiocd/k3baudiojobtempdata.cpp new file mode 100644 index 0000000..af98c2e --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiojobtempdata.cpp @@ -0,0 +1,132 @@ +/* + * + * $Id: k3baudiojobtempdata.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudiojobtempdata.h" +#include "k3baudiodoc.h" +#include "k3baudiotrack.h" +#include +#include +#include +#include + +#include +#include +#include + +#include + + +class K3bAudioJobTempData::Private +{ +public: + Private( K3bAudioDoc* _doc ) + : doc(_doc) { + } + + QValueVector bufferFiles; + QValueVector infFiles; + QString tocFile; + + K3bAudioDoc* doc; +}; + + +K3bAudioJobTempData::K3bAudioJobTempData( K3bAudioDoc* doc, QObject* parent, const char* name ) + : QObject( parent, name ) +{ + d = new Private( doc ); +} + + +K3bAudioJobTempData::~K3bAudioJobTempData() +{ + delete d; +} + + +const QString& K3bAudioJobTempData::bufferFileName( int track ) +{ + if( (int)d->bufferFiles.count() < track ) + prepareTempFileNames(); + return d->bufferFiles.at(track-1); +} + +const QString& K3bAudioJobTempData::bufferFileName( K3bAudioTrack* track ) +{ + return bufferFileName( track->trackNumber() ); +} + + +const QString& K3bAudioJobTempData::tocFileName() +{ + if( d->tocFile.isEmpty() ) + prepareTempFileNames(); + return d->tocFile; +} + + +const QString& K3bAudioJobTempData::infFileName( int track ) +{ + if( (int)d->infFiles.count() < track ) + prepareTempFileNames(); + return d->infFiles.at( track - 1 ); +} + +const QString& K3bAudioJobTempData::infFileName( K3bAudioTrack* track ) +{ + return infFileName( track->trackNumber() ); +} + + +K3bAudioDoc* K3bAudioJobTempData::doc() const +{ + return d->doc; +} + + +void K3bAudioJobTempData::prepareTempFileNames( const QString& path ) +{ + d->bufferFiles.clear(); + d->infFiles.clear(); + + QString prefix = K3b::findUniqueFilePrefix( "k3b_audio_", path ) + "_"; + + for( int i = 0; i < d->doc->numOfTracks(); i++ ) { + d->bufferFiles.append( prefix + QString::number( i+1 ).rightJustify( 2, '0' ) + ".wav" ); + d->infFiles.append( prefix + QString::number( i+1 ).rightJustify( 2, '0' ) + ".inf" ); + } + + d->tocFile = prefix + ".toc"; +} + + +void K3bAudioJobTempData::cleanup() +{ + for( uint i = 0; i < d->infFiles.count(); ++i ) { + if( QFile::exists( d->infFiles[i] ) ) + QFile::remove( d->infFiles[i] ); + } + + for( uint i = 0; i < d->bufferFiles.count(); ++i ) { + if( QFile::exists( d->bufferFiles[i] ) ) + QFile::remove( d->bufferFiles[i] ); + } + + if( QFile::exists( d->tocFile ) ) + QFile::remove( d->tocFile ); +} + + +#include "k3baudiojobtempdata.moc" diff --git a/libk3b/projects/audiocd/k3baudiojobtempdata.h b/libk3b/projects/audiocd/k3baudiojobtempdata.h new file mode 100644 index 0000000..72b753f --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiojobtempdata.h @@ -0,0 +1,64 @@ +/* + * + * $Id: k3baudiojobtempdata.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_AUDIO_JOB_TEMPDATA_H_ +#define _K3B_AUDIO_JOB_TEMPDATA_H_ + +#include +#include + +class K3bAudioTrack; +class K3bAudioDoc; +class QTextStream; + + +class K3bAudioJobTempData : public QObject +{ + Q_OBJECT + + public: + K3bAudioJobTempData( K3bAudioDoc* doc, QObject* parent = 0, const char* name = 0 ); + ~K3bAudioJobTempData(); + + const QString& bufferFileName( int track ); + const QString& bufferFileName( K3bAudioTrack* track ); + + const QString& infFileName( int track ); + const QString& infFileName( K3bAudioTrack* track ); + + const QString& tocFileName(); + + K3bAudioDoc* doc() const; + + /** + * use this if you want + * a specific directory + * it defaults to the default K3b temp dir + */ + void prepareTempFileNames( const QString& path = QString::null ); + + /** + * remove all temp files (this does not include the audio buffer files + * since these are not created and thus not handled by the K3bAudioJobTempData) + */ + void cleanup(); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/audiocd/k3baudiomaxspeedjob.cpp b/libk3b/projects/audiocd/k3baudiomaxspeedjob.cpp new file mode 100644 index 0000000..975ab89 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiomaxspeedjob.cpp @@ -0,0 +1,224 @@ +/* + * + * $Id: k3baudiomaxspeedjob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudiomaxspeedjob.h" +#include "k3baudiotrack.h" +#include "k3baudiodatasource.h" +#include "k3baudiodoc.h" +#include "k3baudiocdtracksource.h" +#include "k3baudiodatasourceiterator.h" + +#include + +#include + +#include +#include + +#include + + +class K3bAudioMaxSpeedJob::WorkThread : public K3bThread +{ +public: + WorkThread( K3bAudioDoc* doc ); + ~WorkThread(); + + void run(); + + int speedTest( K3bAudioDataSource* source ); + void cancel(); + int maxSpeedByMedia() const; + + int maxSpeed; + +private: + K3bAudioDoc* m_doc; + bool m_canceled; + char* m_buffer; +}; + + +K3bAudioMaxSpeedJob::WorkThread::WorkThread( K3bAudioDoc* doc ) + : K3bThread(), + m_doc(doc), + m_canceled(false) +{ + m_buffer = new char[2352*10]; +} + + +K3bAudioMaxSpeedJob::WorkThread::~WorkThread() +{ + delete [] m_buffer; +} + + +void K3bAudioMaxSpeedJob::WorkThread::run() +{ + kdDebug() << k_funcinfo << endl; + m_canceled = false; + + emitStarted(); + + K3bAudioDataSourceIterator it( m_doc ); + + // count sources for minimal progress info + int numSources = 0; + int sourcesDone = 0; + while( it.current() ) { + ++numSources; + it.next(); + } + + bool success = true; + maxSpeed = 175*1000; + it.first(); + + while( it.current() && !m_canceled ) { + if( !it.current()->seek(0) ) { + kdDebug() << "(K3bAudioMaxSpeedJob) seek failed." << endl; + success = false; + break; + } + + // read some data + int speed = speedTest( it.current() ); + + ++sourcesDone; + emitPercent( 100*numSources/sourcesDone ); + + if( speed < 0 ) { + success = false; + break; + } + else if( speed > 0 ) { + // update the max speed + maxSpeed = QMIN( maxSpeed, speed ); + } + + it.next(); + } + + if( m_canceled ) { + emitCanceled(); + success = false; + } + + if( success ) + kdDebug() << "(K3bAudioMaxSpeedJob) max speed: " << maxSpeed << endl; + + emitFinished( success ); +} + +// returns the amount of data read from this source +int K3bAudioMaxSpeedJob::WorkThread::speedTest( K3bAudioDataSource* source ) +{ + // + // in case of an audio track source we only test when the cd is inserted since asking the user would + // confuse him a lot. + // + // FIXME: there is still the problem of the spin up time. + // + if( K3bAudioCdTrackSource* cdts = dynamic_cast( source ) ) { + if( K3bDevice::Device* dev = cdts->searchForAudioCD() ) { + cdts->setDevice( dev ); + } + else { + kdDebug() << "(K3bAudioMaxSpeedJob) ignoring audio cd track source." << endl; + return 0; + } + } + + QTime t; + int dataRead = 0; + int r = 0; + + // start the timer + t.start(); + + // read ten seconds of audio data. This is some value which seemed about right. :) + while( dataRead < 2352*75*10 && (r = source->read( m_buffer, 2352*10 )) > 0 ) { + dataRead += r; + } + + // elapsed millisec + int usedT = t.elapsed(); + + if( r < 0 ) { + kdDebug() << "(K3bAudioMaxSpeedJob) read failure." << endl; + return -1; + } + + // KB/sec (add 1 millisecond to avoid division by 0) + int throughput = (dataRead*1000+usedT)/(usedT+1)/1024; + kdDebug() << "(K3bAudioMaxSpeedJob) throughput: " << throughput + << " (" << dataRead << "/" << usedT << ")" << endl; + + + return throughput; +} + + +void K3bAudioMaxSpeedJob::WorkThread::cancel() +{ + kdDebug() << k_funcinfo << endl; + m_canceled = true; +} + + +int K3bAudioMaxSpeedJob::WorkThread::maxSpeedByMedia() const +{ + int s = 0; + + QValueList speeds = m_doc->burner()->determineSupportedWriteSpeeds(); + // simply use what we have and let the writer decide if the speeds are empty + if( !speeds.isEmpty() ) { + // start with the highest speed and go down the list until we are below our max + QValueListIterator it = speeds.end(); + --it; + while( *it > maxSpeed && it != speeds.begin() ) + --it; + + // this is the first valid speed or the lowest supported one + s = *it; + kdDebug() << "(K3bAudioMaxSpeedJob) using speed factor: " << (s/175) << endl; + } + + return s; +} + + + + +K3bAudioMaxSpeedJob::K3bAudioMaxSpeedJob( K3bAudioDoc* doc, K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bThreadJob( jh, parent, name ) +{ + m_thread = new WorkThread( doc ); + setThread( m_thread ); +} + + +K3bAudioMaxSpeedJob::~K3bAudioMaxSpeedJob() +{ + delete m_thread; +} + + +int K3bAudioMaxSpeedJob::maxSpeed() const +{ + return m_thread->maxSpeedByMedia(); +} +#include "k3baudiomaxspeedjob.moc" diff --git a/libk3b/projects/audiocd/k3baudiomaxspeedjob.h b/libk3b/projects/audiocd/k3baudiomaxspeedjob.h new file mode 100644 index 0000000..876bc7f --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiomaxspeedjob.h @@ -0,0 +1,43 @@ +/* + * + * $Id: k3baudiomaxspeedjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_MAX_SPEED_JOB_H_ +#define _K3B_AUDIO_MAX_SPEED_JOB_H_ + +#include + +class K3bAudioDoc; + + +class K3bAudioMaxSpeedJob : public K3bThreadJob +{ + Q_OBJECT + + public: + K3bAudioMaxSpeedJob( K3bAudioDoc* doc, K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bAudioMaxSpeedJob(); + + /** + * KB/sec + * Only valid if the job finished successfully. + */ + int maxSpeed() const; + + private: + class WorkThread; + WorkThread* m_thread; +}; + +#endif diff --git a/libk3b/projects/audiocd/k3baudionormalizejob.cpp b/libk3b/projects/audiocd/k3baudionormalizejob.cpp new file mode 100644 index 0000000..782712b --- /dev/null +++ b/libk3b/projects/audiocd/k3baudionormalizejob.cpp @@ -0,0 +1,205 @@ +/* + * + * $Id: k3baudionormalizejob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3baudionormalizejob.h" +#include +#include +#include + +#include +#include + + +K3bAudioNormalizeJob::K3bAudioNormalizeJob( K3bJobHandler* hdl, QObject* parent, const char* name ) + : K3bJob( hdl, parent, name ), + m_process(0) +{ +} + + +K3bAudioNormalizeJob::~K3bAudioNormalizeJob() +{ + if( m_process ) + delete m_process; +} + + +void K3bAudioNormalizeJob::start() +{ + m_canceled = false; + m_currentAction = COMPUTING_LEVELS; + m_currentTrack = 1; + + jobStarted(); + + if( m_process ) + delete m_process; + + m_process = new K3bProcess(); + connect( m_process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotStdLine(const QString&)) ); + connect( m_process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited(KProcess*)) ); + + const K3bExternalBin* bin = k3bcore->externalBinManager()->binObject( "normalize-audio" ); + + if( !bin ) { + emit infoMessage( i18n("Could not find normalize-audio executable."), ERROR ); + jobFinished(false); + return; + } + + if( !bin->copyright.isEmpty() ) + emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3").arg(bin->name()).arg(bin->version).arg(bin->copyright), INFO ); + + // create the commandline + *m_process << bin; + + // additional user parameters from config + const QStringList& params = bin->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *m_process << *it; + + // end the options + *m_process << "--"; + + // add the files + for( uint i = 0; i < m_files.count(); ++i ) + *m_process << m_files[i]; + + // now start the process + if( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) { + // something went wrong when starting the program + // it "should" be the executable + kdDebug() << "(K3bAudioNormalizeJob) could not start normalize-audio" << endl; + emit infoMessage( i18n("Could not start normalize-audio."), K3bJob::ERROR ); + jobFinished(false); + } +} + + +void K3bAudioNormalizeJob::cancel() +{ + m_canceled = true; + + if( m_process ) + if( m_process->isRunning() ) { + m_process->kill(); + } +} + + +void K3bAudioNormalizeJob::slotStdLine( const QString& line ) +{ + // percent, subPercent, newTask (compute level and adjust) + + // emit newSubTask( i18n("Normalizing track %1 of %2 (%3)").arg(t).arg(tt).arg(m_files.at(t-1)) ); + + emit debuggingOutput( "normalize-audio", line ); + + // wenn "% done" drin: + // wenn ein --% drin ist, so beginnt ein neuer track + // sonst prozent parsen "batch xxx" ist der fortschritt der action + // also ev. den batch fortschritt * 1/2 + + if( line.startsWith( "Applying adjustment" ) ) { + if( m_currentAction == COMPUTING_LEVELS ) { + // starting the adjustment with track 1 + m_currentTrack = 1; + m_currentAction = ADJUSTING_LEVELS; + } + } + + else if( line.contains( "already normalized" ) ) { + // no normalization necessary for the current track + emit infoMessage( i18n("Track %1 is already normalized.").arg(m_currentTrack), INFO ); + m_currentTrack++; + } + + else if( line.contains( "--% done") ) { + if( m_currentAction == ADJUSTING_LEVELS ) { + emit newTask( i18n("Adjusting volume level for track %1 of %2").arg(m_currentTrack).arg(m_files.count()) ); + kdDebug() << "(K3bAudioNormalizeJob) adjusting level for track " + << m_currentTrack + << " " + << m_files.at(m_currentTrack-1) + << endl; + } + else { + emit newTask( i18n("Computing level for track %1 of %2").arg(m_currentTrack).arg(m_files.count()) ); + kdDebug() << "(K3bAudioNormalizeJob) computing level for track " + << m_currentTrack + << " " + << m_files.at(m_currentTrack-1) + << endl; + } + + m_currentTrack++; + } + + else if( int pos = line.find( "% done" ) > 0 ) { + // parse progress: "XXX% done" and "batch XXX% done" + pos -= 3; + bool ok; + // TODO: do not use fixed values + // track progress starts at position 19 in version 0.7.6 + int p = line.mid( 19, 3 ).toInt(&ok); + if( ok ) + emit subPercent( p ); + else + kdDebug() << "(K3bAudioNormalizeJob) subPercent parsing error at pos " + << 19 << " in line '" << line.mid( 19, 3 ) << "'" << endl; + + // batch progress starts at position 50 in version 0.7.6 + p = line.mid( 50, 3 ).toInt(&ok); + if( ok && m_currentAction == COMPUTING_LEVELS ) + emit percent( (int)((double)p/2.0) ); + else if( ok && m_currentAction == ADJUSTING_LEVELS ) + emit percent( 50 + (int)((double)p/2.0) ); + else + kdDebug() << "(K3bAudioNormalizeJob) percent parsing error at pos " + << 50 << " in line '" << line.mid( 50, 3 ) << "'" << endl; + + } +} + + +void K3bAudioNormalizeJob::slotProcessExited( KProcess* p ) +{ + if( p->normalExit() ) { + switch( p->exitStatus() ) { + case 0: + emit infoMessage( i18n("Successfully normalized all tracks."), SUCCESS ); + jobFinished(true); + break; + default: + if( !m_canceled ) { + emit infoMessage( i18n("%1 returned an unknown error (code %2).").arg("normalize-audio").arg(p->exitStatus()), + K3bJob::ERROR ); + emit infoMessage( i18n("Please send me an email with the last output."), K3bJob::ERROR ); + emit infoMessage( i18n("Error while normalizing tracks."), ERROR ); + } + else + emit canceled(); + jobFinished(false); + break; + } + } + else { + emit infoMessage( i18n("%1 did not exit cleanly.").arg("Normalize"), K3bJob::ERROR ); + jobFinished( false ); + } +} + +#include "k3baudionormalizejob.moc" diff --git a/libk3b/projects/audiocd/k3baudionormalizejob.h b/libk3b/projects/audiocd/k3baudionormalizejob.h new file mode 100644 index 0000000..e56086b --- /dev/null +++ b/libk3b/projects/audiocd/k3baudionormalizejob.h @@ -0,0 +1,63 @@ +/* + * + * $Id: k3baudionormalizejob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_AUDIO_NORMALIZE_JOB_H_ +#define _K3B_AUDIO_NORMALIZE_JOB_H_ + + +#include + +#include + +class K3bProcess; +class KProcess; + + +class K3bAudioNormalizeJob : public K3bJob +{ + Q_OBJECT + + public: + K3bAudioNormalizeJob( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bAudioNormalizeJob(); + + public slots: + void start(); + void cancel(); + + void setFilesToNormalize( const QValueVector& files ) { m_files = files; } + + private slots: + void slotStdLine( const QString& line ); + void slotProcessExited( KProcess* p ); + + private: + K3bProcess* m_process; + + QValueVector m_files; + bool m_canceled; + + enum Action { + COMPUTING_LEVELS, + ADJUSTING_LEVELS + }; + + int m_currentAction; + int m_currentTrack; +}; + + +#endif diff --git a/libk3b/projects/audiocd/k3baudiotrack.cpp b/libk3b/projects/audiocd/k3baudiotrack.cpp new file mode 100644 index 0000000..a1d12e4 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiotrack.cpp @@ -0,0 +1,628 @@ +/* + * + * $Id: k3baudiotrack.cpp 620139 2007-01-05 11:59:05Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3baudiotrack.h" +#include "k3baudiodoc.h" +#include "k3baudiodatasource.h" + +#include +#include +#include + +#include + +#include + + + +class K3bAudioTrack::Private +{ +public: + Private() { + cdTextValidator = new K3bCdTextValidator(); + } + + ~Private() { + delete cdTextValidator; + } + + K3bCdTextValidator* cdTextValidator; +}; + + +K3bAudioTrack::K3bAudioTrack() + : m_parent(0), + m_copy(false), + m_preEmp(false), + m_index0Offset(150), + m_prev(0), + m_next(0), + m_firstSource(0), + m_currentSource(0), + m_alreadyReadBytes(0), + m_currentlyDeleting(false) +{ + d = new Private; +} + + +K3bAudioTrack::K3bAudioTrack( K3bAudioDoc* parent ) + : m_parent(parent), + m_copy(false), + m_preEmp(false), + m_index0Offset(150), + m_prev(0), + m_next(0), + m_firstSource(0), + m_currentSource(0), + m_alreadyReadBytes(0), + m_currentlyDeleting(false) +{ + d = new Private; +} + + +K3bAudioTrack::~K3bAudioTrack() +{ + kdDebug() << "(K3bAudioTrack::~K3bAudioTrack) " << this << endl; + // + // It is crucial that we do not emit the changed signal here because otherwise + // the doc will delete us again once we are empty! + // + m_currentlyDeleting = true; + + // fix the list + take(); + + kdDebug() << "(K3bAudioTrack::~K3bAudioTrack) deleting sources." << endl; + + // delete all sources + while( m_firstSource ) + delete m_firstSource->take(); + + kdDebug() << "(K3bAudioTrack::~K3bAudioTrack) finished" << endl; + + delete d; +} + + +void K3bAudioTrack::emitChanged() +{ + if( m_parent ) + m_parent->slotTrackChanged( this ); +} + + +void K3bAudioTrack::setArtist( const QString& a ) +{ + setPerformer( a ); +} + + +void K3bAudioTrack::setPerformer( const QString& a ) +{ + QString s( a ); + d->cdTextValidator->fixup( s ); + m_cdText.setPerformer(s); + emitChanged(); +} + + +void K3bAudioTrack::setTitle( const QString& t ) +{ + QString s( t ); + d->cdTextValidator->fixup( s ); + m_cdText.setTitle(s); + emitChanged(); +} + + +void K3bAudioTrack::setArranger( const QString& t ) +{ + QString s( t ); + d->cdTextValidator->fixup( s ); + m_cdText.setArranger(s); + emitChanged(); +} + + +void K3bAudioTrack::setSongwriter( const QString& t ) +{ + QString s( t ); + d->cdTextValidator->fixup( s ); + m_cdText.setSongwriter(s); + emitChanged(); +} + + +void K3bAudioTrack::setComposer( const QString& t ) +{ + QString s( t ); + d->cdTextValidator->fixup( s ); + m_cdText.setComposer(s); + emitChanged(); +} + + +void K3bAudioTrack::setIsrc( const QString& t ) +{ + m_cdText.setIsrc(t); + emitChanged(); +} + + +void K3bAudioTrack::setCdTextMessage( const QString& t ) +{ + QString s( t ); + d->cdTextValidator->fixup( s ); + m_cdText.setMessage(s); + emitChanged(); +} + + +void K3bAudioTrack::setCdText( const K3bDevice::TrackCdText& cdtext ) +{ + m_cdText = cdtext; + emitChanged(); +} + + +K3bAudioDataSource* K3bAudioTrack::lastSource() const +{ + K3bAudioDataSource* s = m_firstSource; + while( s && s->next() ) + s = s->next(); + return s; +} + + +bool K3bAudioTrack::inList() const +{ + if( doc() ) + return ( doc()->firstTrack() == this || m_prev != 0 ); + else + return false; +} + + +K3b::Msf K3bAudioTrack::length() const +{ + K3b::Msf length; + K3bAudioDataSource* source = m_firstSource; + while( source ) { + length += source->length(); + source = source->next(); + } + return length; +} + + +KIO::filesize_t K3bAudioTrack::size() const +{ + return length().audioBytes(); +} + + +unsigned int K3bAudioTrack::trackNumber() const +{ + if( m_prev ) + return m_prev->trackNumber() + 1; + else + return 1; +} + + +K3b::Msf K3bAudioTrack::index0() const +{ + // we save the index0Offset as length of the resulting pregap + // this way the length of the track does not need to be ready + // when creating the track. + return length() - m_index0Offset; +} + + +K3b::Msf K3bAudioTrack::postGap() const +{ + if( next() ) + return m_index0Offset; + else + return 0; +} + + +void K3bAudioTrack::setIndex0( const K3b::Msf& msf ) +{ + if( msf == 0 ) + m_index0Offset = 0; + else + m_index0Offset = length() - msf; +} + + +K3bAudioTrack* K3bAudioTrack::take() +{ + if( inList() ) { + if( !m_prev ) + doc()->setFirstTrack( m_next ); + if( !m_next ) + doc()->setLastTrack( m_prev ); + + if( m_prev ) + m_prev->m_next = m_next; + if( m_next ) + m_next->m_prev = m_prev; + + m_prev = m_next = 0; + + // remove from doc + if( m_parent ) + m_parent->slotTrackRemoved(this); + m_parent = 0; + } + + return this; +} + + +void K3bAudioTrack::moveAfter( K3bAudioTrack* track ) +{ + kdDebug() << "(K3bAudioTrack::moveAfter( " << track << " )" << endl; + if( !track ) { + if( !doc() ) { + kdDebug() << "(K3bAudioTrack::moveAfter) no parent set" << endl; + return; + } + + // make sure we do not mess up the list + if( doc()->lastTrack() ) + moveAfter( doc()->lastTrack() ); + else { + doc()->setFirstTrack( take() ); + doc()->setLastTrack( this ); + } + } + else if( track == this ) { + kdDebug() << "(K3bAudioTrack::moveAfter) trying to move this after this." << endl; + return; + } + else { + // remove this from the list + take(); + + // set the new parent doc + m_parent = track->doc(); + + K3bAudioTrack* oldNext = track->m_next; + + // set track as prev + track->m_next = this; + m_prev = track; + + // set oldNext as next + if( oldNext ) + oldNext->m_prev = this; + m_next = oldNext; + + if( !m_prev ) + doc()->setFirstTrack( this ); + if( !m_next ) + doc()->setLastTrack( this ); + } + + emitChanged(); +} + + +void K3bAudioTrack::moveAhead( K3bAudioTrack* track ) +{ + if( !track ) { + if( !doc() ) { + kdDebug() << "(K3bAudioTrack::moveAfter) no parent set" << endl; + return; + } + + // make sure we do not mess up the list + if( doc()->firstTrack() ) + moveAhead( doc()->firstTrack() ); + else { + doc()->setFirstTrack( take() ); + doc()->setLastTrack( this ); + } + } + else if( track == this ) { + kdDebug() << "(K3bAudioTrack::moveAhead) trying to move this ahead of this." << endl; + return; + } + else { + // remove this from the list + take(); + + // set the new parent doc + m_parent = track->doc(); + + K3bAudioTrack* oldPrev = track->m_prev; + + // set track as next + m_next = track; + track->m_prev = this; + + // set oldPrev as prev + m_prev = oldPrev; + if( oldPrev ) + oldPrev->m_next = this; + + if( !m_prev ) + doc()->setFirstTrack( this ); + if( !m_next ) + doc()->setLastTrack( this ); + } + + emitChanged(); +} + + +void K3bAudioTrack::merge( K3bAudioTrack* trackToMerge, K3bAudioDataSource* sourceAfter ) +{ + kdDebug() << "(K3bAudioTrack::merge) " << trackToMerge << " into " << this << endl; + if( this == trackToMerge ) { + kdDebug() << "(K3bAudioTrack::merge) trying to merge this with this." << endl; + return; + } + + // remove the track to merge to make sure it does not get deleted by the doc too early + trackToMerge->take(); + + // in case we prepend all of trackToMerge's sources + if( !sourceAfter ) { + kdDebug() << "(K3bAudioTrack::merge) merging " << trackToMerge->firstSource() << endl; + if( m_firstSource ) { + trackToMerge->firstSource()->moveAhead( m_firstSource ); + } + else { + addSource( trackToMerge->firstSource()->take() ); + } + sourceAfter = m_firstSource; + } + + kdDebug() << "(K3bAudioTrack::merge) now merge the other sources." << endl; + // now merge all sources into this track + while( trackToMerge->firstSource() ) { + K3bAudioDataSource* s = trackToMerge->firstSource(); + kdDebug() << "(K3bAudioTrack::merge) merging source " << s << " from track " << s->track() << " into track " + << this << " after source " << sourceAfter << endl; + s->moveAfter( sourceAfter ); + sourceAfter = s; + } + + // TODO: should we also merge the indices? + + // now we can safely delete the track we merged + delete trackToMerge; + + kdDebug() << "(K3bAudioTrack::merge) finished" << endl; + + emitChanged(); +} + + +void K3bAudioTrack::setFirstSource( K3bAudioDataSource* source ) +{ + // reset the reading stuff since this might be a completely new source list + m_currentSource = 0; + m_alreadyReadBytes = 0; + + m_firstSource = source; + while( source ) { + source->m_track = this; + source = source->next(); + } + + emitChanged(); +} + + +void K3bAudioTrack::addSource( K3bAudioDataSource* source ) +{ + if( !source ) + return; + + K3bAudioDataSource* s = m_firstSource; + while( s && s->next() ) + s = s->next(); + if( s ) + source->moveAfter( s ); + else + setFirstSource( source->take() ); +} + + +void K3bAudioTrack::sourceChanged( K3bAudioDataSource* ) +{ + if( m_currentlyDeleting ) + return; + + // TODO: update indices + + if( m_index0Offset > length() ) + m_index0Offset = length()-1; + + emitChanged(); +} + + +int K3bAudioTrack::numberSources() const +{ + K3bAudioDataSource* source = m_firstSource; + int i = 0; + while( source ) { + source = source->next(); + ++i; + } + return i; +} + + +bool K3bAudioTrack::seek( const K3b::Msf& msf ) +{ + K3bAudioDataSource* source = m_firstSource; + + K3b::Msf pos; + while( source && pos + source->length() < msf ) { + pos += source->length(); + source = source->next(); + } + + if( source ) { + m_currentSource = source; + m_alreadyReadBytes = msf.audioBytes(); + return source->seek( msf - pos ); + } + else + return false; +} + + +int K3bAudioTrack::read( char* data, unsigned int max ) +{ + if( !m_currentSource ) { + m_currentSource = m_firstSource; + if( m_currentSource ) + m_currentSource->seek(0); + m_alreadyReadBytes = 0; + } + + int readData = m_currentSource->read( data, max ); + if( readData == 0 ) { + m_currentSource = m_currentSource->next(); + if( m_currentSource ) { + m_currentSource->seek(0); + return read( data, max ); // read from next source + } + } + + m_alreadyReadBytes += readData; + + return readData; +} + + +K3bAudioTrack* K3bAudioTrack::copy() const +{ + K3bAudioTrack* track = new K3bAudioTrack(); + + track->m_copy = m_copy; + track->m_preEmp = m_preEmp; + track->m_index0Offset = m_index0Offset; + track->m_cdText = m_cdText; + K3bAudioDataSource* source = m_firstSource; + while( source ) { + track->addSource( source->copy() ); + source = source->next(); + } + + return track; +} + + +K3bAudioTrack* K3bAudioTrack::split( const K3b::Msf& pos ) +{ + if( pos < length() ) { + // search the source + // pos will be the first sector of the new track + K3b::Msf currentPos; + K3bAudioDataSource* source = firstSource(); + while( source && currentPos + source->length() <= pos ) { + currentPos += source->length(); + source = source->next(); + } + + K3bAudioDataSource* splitSource = 0; + if( currentPos > 0 && currentPos == pos ) { + // no need to split a source + splitSource = source; + } + else { + splitSource = source->split( pos - currentPos ); + } + + // the new track should include all sources from splitSource and below + K3bAudioTrack* splitTrack = new K3bAudioTrack(); + splitTrack->m_cdText = m_cdText; + source = splitSource; + while( source ) { + K3bAudioDataSource* addSource = source; + source = source->next(); + splitTrack->addSource( addSource ); + } + + kdDebug() << "(K3bAudioTrack) moving track " << splitTrack << " after this (" << this << ") with parent " << doc() << endl; + splitTrack->moveAfter( this ); + + return splitTrack; + } + else + return 0; +} + + +K3bDevice::Track K3bAudioTrack::toCdTrack() const +{ + if( !inList() ) + return K3bDevice::Track(); + + K3b::Msf firstSector; + K3bAudioTrack* track = doc()->firstTrack(); + while( track != this ) { + firstSector += track->length(); + track = track->next(); + } + + K3bDevice::Track cdTrack( firstSector, + firstSector + length() - 1, + K3bDevice::Track::AUDIO ); + + // FIXME: auch im audiotrack copy permitted + cdTrack.setCopyPermitted( !copyProtection() ); + cdTrack.setPreEmphasis( preEmp() ); + + // FIXME: add indices != 0 + + // no index 0 for the last track. Or should we allow this??? + if( doc()->lastTrack() != this ) + cdTrack.setIndex0( index0() ); + + // FIXME: convert to QCString + // cdTrack.setIsrc( isrc() ); + + return cdTrack; +} + + +void K3bAudioTrack::debug() +{ + kdDebug() << "Track " << this << endl + << " Prev: " << m_prev << endl + << " Next: " << m_next << endl + << " Sources:" << endl; + K3bAudioDataSource* s = m_firstSource; + while( s ) { + kdDebug() << " " << s << " - Prev: " << s->prev() << " Next: " << s->next() << endl; + s = s->next(); + } +} + + + diff --git a/libk3b/projects/audiocd/k3baudiotrack.h b/libk3b/projects/audiocd/k3baudiotrack.h new file mode 100644 index 0000000..ab0ee1b --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiotrack.h @@ -0,0 +1,214 @@ +/* + * + * $Id: k3baudiotrack.h 620139 2007-01-05 11:59:05Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BAUDIOTRACK_H +#define K3BAUDIOTRACK_H + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include "k3b_export.h" + +class K3bAudioDecoder; +class K3bAudioDataSource; +class K3bAudioDoc; + + +/** + * @author Sebastian Trueg + */ +class LIBK3B_EXPORT K3bAudioTrack +{ + friend class K3bAudioDataSource; + friend class K3bAudioDoc; + + public: + K3bAudioTrack(); + K3bAudioTrack( K3bAudioDoc* parent ); + ~K3bAudioTrack(); + + K3bAudioDoc* doc() const { return m_parent; } + + K3bDevice::Track toCdTrack() const; + + /** + * @return length of track in frames + */ + K3b::Msf length() const; + KIO::filesize_t size() const; + + const QString& artist() const { return m_cdText.performer(); } + const QString& performer() const { return m_cdText.performer(); } + const QString& title() const { return m_cdText.title(); } + const QString& arranger() const { return m_cdText.arranger(); } + const QString& songwriter() const { return m_cdText.songwriter(); } + const QString& composer() const { return m_cdText.composer(); } + const QString& isrc() const { return m_cdText.isrc(); } + const QString& cdTextMessage() const { return m_cdText.message(); } + const K3bDevice::TrackCdText& cdText() const { return m_cdText; } + + bool copyProtection() const { return m_copy; } + bool preEmp() const { return m_preEmp; } + + /** + * @obsolete use setPerformer + **/ + void setArtist( const QString& a ); + void setPerformer( const QString& a ); + void setTitle( const QString& t ); + void setArranger( const QString& t ); + void setSongwriter( const QString& t ); + void setComposer( const QString& t ); + void setIsrc( const QString& t ); + void setCdTextMessage( const QString& t ); + + void setCdText( const K3bDevice::TrackCdText& cdtext ); + + void setPreEmp( bool b ) { m_preEmp = b; emitChanged(); } + void setCopyProtection( bool b ) { m_copy = b; emitChanged(); } + + K3b::Msf index0() const; + /** + * The length of the postgap, ie. the number of blocks with index0. + * This is always 0 for the last track. + */ + K3b::Msf postGap() const; + void setIndex0( const K3b::Msf& ); + + /** + * \return The track number starting at 1. + */ + unsigned int trackNumber() const; + + /** + * Remove this track from the list and return it. + */ + K3bAudioTrack* take(); + + /** + * Move this track after @p track. + * If @p track is null this track will be merged into the beginning + * of the docs list. + */ + void moveAfter( K3bAudioTrack* track ); + + /** + * Move this track ahead of @p track. + * If @p track is null this track will be appended to the end + * of the docs list. + */ + void moveAhead( K3bAudioTrack* track ); + + /** + * Merge @p trackToMerge into this one. + */ + void merge( K3bAudioTrack* trackToMerge, K3bAudioDataSource* sourceAfter = 0 ); + + K3bAudioTrack* prev() const { return m_prev; } + K3bAudioTrack* next() const { return m_next; } + + /** + * Use with care. + */ + void setFirstSource( K3bAudioDataSource* source ); + K3bAudioDataSource* firstSource() const { return m_firstSource; } + K3bAudioDataSource* lastSource() const; + int numberSources() const; + + /** + * Append source to the end of the sources list. + */ + void addSource( K3bAudioDataSource* source ); + + bool seek( const K3b::Msf& ); + + /** + * Read data from the track. + * + * @return number of read bytes + */ + int read( char* data, unsigned int max ); + + /** + * called by K3bAudioDataSource because of the lack of signals + */ + void sourceChanged( K3bAudioDataSource* ); + + /** + * Create a copy of this track containing copies of all the sources + * but not being part of some list. + */ + K3bAudioTrack* copy() const; + + /** + * Split the track at position pos and return the splitted track + * on success. + * The new track will be moved after this track. + * + * \param pos The position at which to split. \a pos will be the + * first frame in the new track. + */ + K3bAudioTrack* split( const K3b::Msf& pos ); + + /** + * Is this track in a list + */ + bool inList() const; + + private: + /** + * Tells the doc that the track has changed + */ + void emitChanged(); + + void debug(); + + K3bAudioDoc* m_parent; + + /** copy protection */ + bool m_copy; + bool m_preEmp; + + K3b::Msf m_index0Offset; + + K3bDevice::TrackCdText m_cdText; + + // list + K3bAudioTrack* m_prev; + K3bAudioTrack* m_next; + + K3bAudioDataSource* m_firstSource; + + + K3bAudioDataSource* m_currentSource; + long long m_alreadyReadBytes; + + bool m_currentlyDeleting; + + class Private; + Private* d; +}; + + +#endif diff --git a/libk3b/projects/audiocd/k3baudiozerodata.cpp b/libk3b/projects/audiocd/k3baudiozerodata.cpp new file mode 100644 index 0000000..f5c985d --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiozerodata.cpp @@ -0,0 +1,115 @@ +/* + * + * $Id: k3baudiozerodata.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3baudiozerodata.h" +#include "k3baudiotrack.h" + +#include + +#include + + +K3bAudioZeroData::K3bAudioZeroData( const K3b::Msf& len ) + : K3bAudioDataSource(), + m_length(len), + m_writtenData(0) +{ +} + + +K3bAudioZeroData::K3bAudioZeroData( const K3bAudioZeroData& zero ) + : K3bAudioDataSource( zero ), + m_length( zero.m_length ), + m_writtenData( 0 ) +{ +} + + +K3bAudioZeroData::~K3bAudioZeroData() +{ +} + + +void K3bAudioZeroData::setLength( const K3b::Msf& msf ) +{ + if( msf > 0 ) + m_length = msf; + else + m_length = 1; // 1 frame + + m_writtenData = 0; + + emitChange(); +} + + +QString K3bAudioZeroData::type() const +{ + return i18n("Silence"); +} + + +QString K3bAudioZeroData::sourceComment() const +{ + return QString::null; +} + + +bool K3bAudioZeroData::seek( const K3b::Msf& msf ) +{ + if( msf < length() ) { + m_writtenData = msf.audioBytes(); + return true; + } + else + return false; +} + + +int K3bAudioZeroData::read( char* data, unsigned int max ) +{ + if( m_writtenData + max > length().audioBytes() ) + max = length().audioBytes() - m_writtenData; + + m_writtenData += max; + + ::memset( data, 0, max ); + + return max; +} + + +K3bAudioDataSource* K3bAudioZeroData::copy() const +{ + return new K3bAudioZeroData( *this ); +} + + +void K3bAudioZeroData::setStartOffset( const K3b::Msf& pos ) +{ + if( pos >= length() ) + setLength( 1 ); + else + setLength( length() - pos ); +} + + +void K3bAudioZeroData::setEndOffset( const K3b::Msf& pos ) +{ + if( pos < 1 ) + setLength( 1 ); + else + setLength( pos ); +} diff --git a/libk3b/projects/audiocd/k3baudiozerodata.h b/libk3b/projects/audiocd/k3baudiozerodata.h new file mode 100644 index 0000000..8cb2911 --- /dev/null +++ b/libk3b/projects/audiocd/k3baudiozerodata.h @@ -0,0 +1,55 @@ +/* + * + * $Id: k3baudiozerodata.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_AUDIO_ZERO_DATA_H_ +#define _K3B_AUDIO_ZERO_DATA_H_ + +#include "k3baudiodatasource.h" +#include "k3b_export.h" + +class LIBK3B_EXPORT K3bAudioZeroData : public K3bAudioDataSource +{ + public: + K3bAudioZeroData( const K3b::Msf& msf = 150 ); + K3bAudioZeroData( const K3bAudioZeroData& ); + ~K3bAudioZeroData(); + + K3b::Msf originalLength() const { return m_length; } + void setLength( const K3b::Msf& msf ); + + QString type() const; + QString sourceComment() const; + + bool seek( const K3b::Msf& ); + int read( char* data, unsigned int max ); + + K3bAudioDataSource* copy() const; + + /** + * Only changes the length + */ + void setStartOffset( const K3b::Msf& ); + + /** + * Only changes the length + */ + void setEndOffset( const K3b::Msf& ); + + private: + K3b::Msf m_length; + unsigned long long m_writtenData; +}; + +#endif diff --git a/libk3b/projects/datacd/Makefile.am b/libk3b/projects/datacd/Makefile.am new file mode 100644 index 0000000..dea5cb2 --- /dev/null +++ b/libk3b/projects/datacd/Makefile.am @@ -0,0 +1,35 @@ +AM_CPPFLAGS= -I$(srcdir)/.. \ + -I$(srcdir)/../../core \ + -I$(srcdir)/../../plugin \ + -I$(srcdir)/../../../libk3bdevice \ + -I$(srcdir)/../../../src \ + -I$(srcdir)/../../tools \ + -I$(srcdir)/../../jobs \ + -I$(srcdir)/../.. \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libdata.la + +libdata_la_SOURCES = k3bdatajob.cpp \ + k3bdatadoc.cpp \ + k3bdataitem.cpp \ + k3bdiritem.cpp \ + k3bfileitem.cpp \ + k3bisoimager.cpp \ + k3bmsinfofetcher.cpp \ + k3bbootitem.cpp \ + k3bisooptions.cpp \ + k3bfilecompilationsizehandler.cpp \ + k3bsessionimportitem.cpp \ + k3bmkisofshandler.cpp \ + k3bdatapreparationjob.cpp + +include_HEADERS = k3bdatadoc.h \ + k3bdatajob.h \ + k3bdataitem.h \ + k3bdiritem.h \ + k3bfileitem.h \ + k3bbootitem.h \ + k3bisooptions.h diff --git a/libk3b/projects/datacd/k3bbootitem.cpp b/libk3b/projects/datacd/k3bbootitem.cpp new file mode 100644 index 0000000..e94830e --- /dev/null +++ b/libk3b/projects/datacd/k3bbootitem.cpp @@ -0,0 +1,58 @@ +/* + * + * $Id: k3bbootitem.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bbootitem.h" +#include "k3bdatadoc.h" +#include "k3bdiritem.h" + +#include + +#include + + +K3bBootItem::K3bBootItem( const QString& fileName, K3bDataDoc* doc, K3bDirItem* dir, const QString& k3bName ) + : K3bFileItem( fileName, doc, dir, k3bName, FILE|BOOT_IMAGE ), + m_noBoot(false), + m_bootInfoTable(false), + m_loadSegment(0), + m_loadSize(0), + m_imageType(FLOPPY) +{ + setExtraInfo( i18n("El Torito Boot image") ); +} + + +K3bBootItem::K3bBootItem( const K3bBootItem& item ) + : K3bFileItem( item ), + m_noBoot( item.m_noBoot ), + m_bootInfoTable( item.m_bootInfoTable ), + m_loadSegment( item.m_loadSegment ), + m_loadSize( item.m_loadSize ), + m_imageType( item.m_imageType ), + m_tempPath( item.m_tempPath ) +{ +} + + +K3bBootItem::~K3bBootItem() +{ + take(); +} + + +K3bDataItem* K3bBootItem::copy() const +{ + return new K3bBootItem( *this ); +} diff --git a/libk3b/projects/datacd/k3bbootitem.h b/libk3b/projects/datacd/k3bbootitem.h new file mode 100644 index 0000000..9dd8704 --- /dev/null +++ b/libk3b/projects/datacd/k3bbootitem.h @@ -0,0 +1,66 @@ +/* + * + * $Id: k3bbootitem.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_BOOT_ITEM_H_ +#define _K3B_BOOT_ITEM_H_ + +#include "k3bfileitem.h" + +class K3bBootItem : public K3bFileItem +{ + public: + K3bBootItem( const QString& fileName, K3bDataDoc* doc, K3bDirItem* dir, const QString& k3bName = 0 ); + K3bBootItem( const K3bBootItem& ); + ~K3bBootItem(); + + K3bDataItem* copy() const; + + bool isHideable() const { return false; } + + bool isBootItem() const { return true; } + + enum imageType { FLOPPY, HARDDISK, NONE }; + + void setNoBoot( bool b ) { m_noBoot = b; } + void setBootInfoTable( bool b ) { m_bootInfoTable = b; } + void setLoadSegment( int s ) { m_loadSegment = s; } + void setLoadSize( int s ) { m_loadSize = s; } + void setImageType( int t ) { m_imageType = t; } + + void setTempPath( const QString& p ) { m_tempPath = p; } + + bool noBoot() const { return m_noBoot; } + bool bootInfoTable() const { return m_bootInfoTable; } + int loadSegment() const { return m_loadSegment; } + int loadSize() const { return m_loadSize; } + int imageType() const { return m_imageType; } + + /** + * mkisofs changes boot images on disk. That is why the iso imager + * buffers them and saves the path to the buffered copy here. + */ + const QString& tempPath() const { return m_tempPath; } + + private: + bool m_noBoot; + bool m_bootInfoTable; + int m_loadSegment; + int m_loadSize; + int m_imageType; + + QString m_tempPath; +}; + +#endif diff --git a/libk3b/projects/datacd/k3bdatadoc.cpp b/libk3b/projects/datacd/k3bdatadoc.cpp new file mode 100644 index 0000000..d12c8d2 --- /dev/null +++ b/libk3b/projects/datacd/k3bdatadoc.cpp @@ -0,0 +1,1376 @@ +/* + * + * $Id: k3bdatadoc.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bdatadoc.h" +#include "k3bfileitem.h" +#include "k3bdiritem.h" +#include "k3bsessionimportitem.h" +#include "k3bdatajob.h" +#include "k3bbootitem.h" +#include "k3bspecialdataitem.h" +#include "k3bfilecompilationsizehandler.h" +#include "k3bmkisofshandler.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include + + +/** + * There are two ways to fill a data project with files and folders: + * \li Use the addUrl and addUrls methods + * \li or create your own K3bDirItems and K3bFileItems. The doc will be properly updated + * by the constructors of the items. + */ +K3bDataDoc::K3bDataDoc( QObject* parent ) + : K3bDoc( parent ) +{ + m_root = 0; + + m_sizeHandler = new K3bFileCompilationSizeHandler(); +} + +K3bDataDoc::~K3bDataDoc() +{ + delete m_root; + delete m_sizeHandler; + // delete m_oldSessionSizeHandler; +} + + +bool K3bDataDoc::newDocument() +{ + clearImportedSession(); + + m_bootCataloge = 0; + m_oldSessionSize = 0; + m_bExistingItemsReplaceAll = m_bExistingItemsIgnoreAll = false; + + if( m_root ) { + while( m_root->children().getFirst() ) + removeItem( m_root->children().getFirst() ); + } + else + m_root = new K3bRootItem( this ); + + m_sizeHandler->clear(); + + m_multisessionMode = AUTO; + m_dataMode = K3b::DATA_MODE_AUTO; + + m_isoOptions = K3bIsoOptions(); + + return K3bDoc::newDocument(); +} + + +QString K3bDataDoc::name() const +{ + return m_isoOptions.volumeID(); +} + + +void K3bDataDoc::setIsoOptions( const K3bIsoOptions& o ) +{ + m_isoOptions = o; + emit changed(); +} + + +void K3bDataDoc::setVolumeID( const QString& v ) +{ + m_isoOptions.setVolumeID( v ); + emit changed(); +} + + +void K3bDataDoc::addUrls( const KURL::List& urls ) +{ + addUrls( urls, root() ); +} + + +void K3bDataDoc::addUrls( const KURL::List& l, K3bDirItem* dir ) +{ + if( !dir ) + dir = root(); + + KURL::List urls = K3b::convertToLocalUrls(l); + + for( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it ) { + const KURL& url = *it; + QFileInfo f( url.path() ); + QString k3bname = f.absFilePath().section( "/", -1 ); + + // filenames cannot end in backslashes (mkisofs problem. See comments in k3bisoimager.cpp (escapeGraftPoint())) + while( k3bname[k3bname.length()-1] == '\\' ) + k3bname.truncate( k3bname.length()-1 ); + + // backup dummy name + if( k3bname.isEmpty() ) + k3bname = "1"; + + K3bDirItem* newDirItem = 0; + + // rename the new item if an item with that name already exists + int cnt = 0; + bool ok = false; + while( !ok ) { + ok = true; + QString name( k3bname ); + if( cnt > 0 ) + name += QString("_%1").arg(cnt); + if( K3bDataItem* oldItem = dir->find( name ) ) { + if( f.isDir() && oldItem->isDir() ) { + // ok, just reuse the dir + newDirItem = static_cast(oldItem); + } + // directories cannot replace files in an old session (I think) + // and also directories can for sure never be replaced (only be reused as above) + // so we always rename if the old item is a dir. + else if( !oldItem->isFromOldSession() || + f.isDir() || + oldItem->isDir() ) { + ++cnt; + ok = false; + } + } + } + if( cnt > 0 ) + k3bname += QString("_%1").arg(cnt); + + // QFileInfo::exists and QFileInfo::isReadable return false for broken symlinks :( + if( f.isDir() && !f.isSymLink() ) { + if( !newDirItem ) { + newDirItem = new K3bDirItem( k3bname, this, dir ); + newDirItem->setLocalPath( url.path() ); // HACK: see k3bdiritem.h + } + + // recursively add all the files in the directory + QStringList dlist = QDir( f.absFilePath() ).entryList( QDir::All|QDir::System|QDir::Hidden ); + dlist.remove("."); + dlist.remove(".."); + KURL::List newUrls; + for( QStringList::Iterator it = dlist.begin(); it != dlist.end(); ++it ) + newUrls.append( KURL::fromPathOrURL( f.absFilePath() + "/" + *it ) ); + addUrls( newUrls, newDirItem ); + } + else if( f.isSymLink() || f.isFile() ) + (void)new K3bFileItem( url.path(), this, dir, k3bname ); + } + + emit changed(); + + setModified( true ); +} + + +bool K3bDataDoc::nameAlreadyInDir( const QString& name, K3bDirItem* dir ) +{ + if( !dir ) + return false; + else + return ( dir->find( name ) != 0 ); +} + + +K3bDirItem* K3bDataDoc::addEmptyDir( const QString& name, K3bDirItem* parent ) +{ + K3bDirItem* item = new K3bDirItem( name, this, parent ); + + setModified( true ); + + return item; +} + + +KIO::filesize_t K3bDataDoc::size() const +{ + if( m_isoOptions.doNotCacheInodes() ) + return root()->blocks().mode1Bytes() + m_oldSessionSize; + else + return m_sizeHandler->blocks( m_isoOptions.followSymbolicLinks() || + !m_isoOptions.createRockRidge() ).mode1Bytes() + m_oldSessionSize; +} + + +KIO::filesize_t K3bDataDoc::burningSize() const +{ + return size() - m_oldSessionSize; //m_oldSessionSizeHandler->size(); +} + + +K3b::Msf K3bDataDoc::length() const +{ + // 1 block consists of 2048 bytes real data + // and 1 block equals to 1 audio frame + // so this is the way to calculate: + + return K3b::Msf( size() / 2048 ); +} + + +K3b::Msf K3bDataDoc::burningLength() const +{ + return K3b::Msf( burningSize() / 2048 ); +} + + +QString K3bDataDoc::typeString() const +{ + return QString::fromLatin1("data"); +} + + +bool K3bDataDoc::loadDocumentData( QDomElement* rootElem ) +{ + if( !root() ) + newDocument(); + + QDomNodeList nodes = rootElem->childNodes(); + + if( nodes.item(0).nodeName() != "general" ) { + kdDebug() << "(K3bDataDoc) could not find 'general' section." << endl; + return false; + } + if( !readGeneralDocumentData( nodes.item(0).toElement() ) ) + return false; + + + // parse options + // ----------------------------------------------------------------- + if( nodes.item(1).nodeName() != "options" ) { + kdDebug() << "(K3bDataDoc) could not find 'options' section." << endl; + return false; + } + if( !loadDocumentDataOptions( nodes.item(1).toElement() ) ) + return false; + // ----------------------------------------------------------------- + + + + // parse header + // ----------------------------------------------------------------- + if( nodes.item(2).nodeName() != "header" ) { + kdDebug() << "(K3bDataDoc) could not find 'header' section." << endl; + return false; + } + if( !loadDocumentDataHeader( nodes.item(2).toElement() ) ) + return false; + // ----------------------------------------------------------------- + + + + // parse files + // ----------------------------------------------------------------- + if( nodes.item(3).nodeName() != "files" ) { + kdDebug() << "(K3bDataDoc) could not find 'files' section." << endl; + return false; + } + + if( m_root == 0 ) + m_root = new K3bRootItem( this ); + + QDomNodeList filesList = nodes.item(3).childNodes(); + for( uint i = 0; i < filesList.count(); i++ ) { + + QDomElement e = filesList.item(i).toElement(); + if( !loadDataItem( e, root() ) ) + return false; + } + + // ----------------------------------------------------------------- + + // + // Old versions of K3b do not properly save the boot catalog location + // and name. So to ensure we have one around even if loading an old project + // file we create a default one here. + // + if( !m_bootImages.isEmpty() && !m_bootCataloge ) + createBootCatalogeItem( m_bootImages.first()->parent() ); + + + informAboutNotFoundFiles(); + + return true; +} + + +bool K3bDataDoc::loadDocumentDataOptions( QDomElement elem ) +{ + QDomNodeList headerList = elem.childNodes(); + for( uint i = 0; i < headerList.count(); i++ ) { + + QDomElement e = headerList.item(i).toElement(); + if( e.isNull() ) + return false; + + if( e.nodeName() == "rock_ridge") + m_isoOptions.setCreateRockRidge( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "joliet") + m_isoOptions.setCreateJoliet( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "udf") + m_isoOptions.setCreateUdf( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "joliet_allow_103_characters") + m_isoOptions.setJolietLong( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_allow_lowercase") + m_isoOptions.setISOallowLowercase( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_allow_period_at_begin") + m_isoOptions.setISOallowPeriodAtBegin( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_allow_31_char") + m_isoOptions.setISOallow31charFilenames( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_omit_version_numbers") + m_isoOptions.setISOomitVersionNumbers( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_omit_trailing_period") + m_isoOptions.setISOomitTrailingPeriod( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_max_filename_length") + m_isoOptions.setISOmaxFilenameLength( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_relaxed_filenames") + m_isoOptions.setISOrelaxedFilenames( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_no_iso_translate") + m_isoOptions.setISOnoIsoTranslate( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_allow_multidot") + m_isoOptions.setISOallowMultiDot( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_untranslated_filenames") + m_isoOptions.setISOuntranslatedFilenames( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "follow_symbolic_links") + m_isoOptions.setFollowSymbolicLinks( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "create_trans_tbl") + m_isoOptions.setCreateTRANS_TBL( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "hide_trans_tbl") + m_isoOptions.setHideTRANS_TBL( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "iso_level") + m_isoOptions.setISOLevel( e.text().toInt() ); + + else if( e.nodeName() == "discard_symlinks") + m_isoOptions.setDiscardSymlinks( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "discard_broken_symlinks") + m_isoOptions.setDiscardBrokenSymlinks( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "preserve_file_permissions") + m_isoOptions.setPreserveFilePermissions( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "force_input_charset") + m_isoOptions.setForceInputCharset( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "input_charset") + m_isoOptions.setInputCharset( e.text() ); + + else if( e.nodeName() == "do_not_cache_inodes" ) + m_isoOptions.setDoNotCacheInodes( e.attributeNode( "activated" ).value() == "yes" ); + + else if( e.nodeName() == "whitespace_treatment" ) { + if( e.text() == "strip" ) + m_isoOptions.setWhiteSpaceTreatment( K3bIsoOptions::strip ); + else if( e.text() == "extended" ) + m_isoOptions.setWhiteSpaceTreatment( K3bIsoOptions::extended ); + else if( e.text() == "extended" ) + m_isoOptions.setWhiteSpaceTreatment( K3bIsoOptions::replace ); + else + m_isoOptions.setWhiteSpaceTreatment( K3bIsoOptions::noChange ); + } + + else if( e.nodeName() == "whitespace_replace_string") + m_isoOptions.setWhiteSpaceTreatmentReplaceString( e.text() ); + + else if( e.nodeName() == "data_track_mode" ) { + if( e.text() == "mode1" ) + m_dataMode = K3b::MODE1; + else if( e.text() == "mode2" ) + m_dataMode = K3b::MODE2; + else + m_dataMode = K3b::DATA_MODE_AUTO; + } + + else if( e.nodeName() == "multisession" ) { + QString mode = e.text(); + if( mode == "start" ) + setMultiSessionMode( START ); + else if( mode == "continue" ) + setMultiSessionMode( CONTINUE ); + else if( mode == "finish" ) + setMultiSessionMode( FINISH ); + else if( mode == "none" ) + setMultiSessionMode( NONE ); + else + setMultiSessionMode( AUTO ); + } + + else if( e.nodeName() == "verify_data" ) + setVerifyData( e.attributeNode( "activated" ).value() == "yes" ); + + else + kdDebug() << "(K3bDataDoc) unknown option entry: " << e.nodeName() << endl; + } + + return true; +} + + +bool K3bDataDoc::loadDocumentDataHeader( QDomElement headerElem ) +{ + QDomNodeList headerList = headerElem.childNodes(); + for( uint i = 0; i < headerList.count(); i++ ) { + + QDomElement e = headerList.item(i).toElement(); + if( e.isNull() ) + return false; + + if( e.nodeName() == "volume_id" ) + m_isoOptions.setVolumeID( e.text() ); + + else if( e.nodeName() == "application_id" ) + m_isoOptions.setApplicationID( e.text() ); + + else if( e.nodeName() == "publisher" ) + m_isoOptions.setPublisher( e.text() ); + + else if( e.nodeName() == "preparer" ) + m_isoOptions.setPreparer( e.text() ); + + else if( e.nodeName() == "volume_set_id" ) + m_isoOptions.setVolumeSetId( e.text() ); + + else if( e.nodeName() == "volume_set_size" ) + m_isoOptions.setVolumeSetSize( e.text().toInt() ); + + else if( e.nodeName() == "volume_set_number" ) + m_isoOptions.setVolumeSetNumber( e.text().toInt() ); + + else if( e.nodeName() == "system_id" ) + m_isoOptions.setSystemId( e.text() ); + + else + kdDebug() << "(K3bDataDoc) unknown header entry: " << e.nodeName() << endl; + } + + return true; +} + + +bool K3bDataDoc::loadDataItem( QDomElement& elem, K3bDirItem* parent ) +{ + K3bDataItem* newItem = 0; + + if( elem.nodeName() == "file" ) { + QDomElement urlElem = elem.firstChild().toElement(); + if( urlElem.isNull() ) { + kdDebug() << "(K3bDataDoc) file-element without url!" << endl; + return false; + } + + QFileInfo f( urlElem.text() ); + + // We canot use exists() here since this always disqualifies broken symlinks + if( !f.isFile() && !f.isSymLink() ) + m_notFoundFiles.append( urlElem.text() ); + + // broken symlinks are not readable according to QFileInfo which is wrong in our case + else if( f.isFile() && !f.isReadable() ) + m_noPermissionFiles.append( urlElem.text() ); + + else if( !elem.attribute( "bootimage" ).isEmpty() ) { + K3bBootItem* bootItem = new K3bBootItem( urlElem.text(), + this, + parent, + elem.attributeNode( "name" ).value() ); + if( elem.attribute( "bootimage" ) == "floppy" ) + bootItem->setImageType( K3bBootItem::FLOPPY ); + else if( elem.attribute( "bootimage" ) == "harddisk" ) + bootItem->setImageType( K3bBootItem::HARDDISK ); + else + bootItem->setImageType( K3bBootItem::NONE ); + bootItem->setNoBoot( elem.attribute( "no_boot" ) == "yes" ); + bootItem->setBootInfoTable( elem.attribute( "boot_info_table" ) == "yes" ); + bootItem->setLoadSegment( elem.attribute( "load_segment" ).toInt() ); + bootItem->setLoadSize( elem.attribute( "load_size" ).toInt() ); + + newItem = bootItem; + } + + else { + newItem = new K3bFileItem( urlElem.text(), + this, + parent, + elem.attributeNode( "name" ).value() ); + } + } + else if( elem.nodeName() == "special" ) { + if( elem.attributeNode( "type" ).value() == "boot cataloge" ) + createBootCatalogeItem( parent )->setK3bName( elem.attributeNode( "name" ).value() ); + } + else if( elem.nodeName() == "directory" ) { + // This is for the VideoDVD project which already contains the *_TS folders + K3bDirItem* newDirItem = 0; + if( K3bDataItem* item = parent->find( elem.attributeNode( "name" ).value() ) ) { + if( item->isDir() ) { + newDirItem = static_cast(item); + } + else { + kdError() << "(K3bDataDoc) INVALID DOCUMENT: item " << item->k3bPath() << " saved twice" << endl; + return false; + } + } + + if( !newDirItem ) + newDirItem = new K3bDirItem( elem.attributeNode( "name" ).value(), this, parent ); + QDomNodeList childNodes = elem.childNodes(); + for( uint i = 0; i < childNodes.count(); i++ ) { + + QDomElement e = childNodes.item(i).toElement(); + if( !loadDataItem( e, newDirItem ) ) + return false; + } + + newItem = newDirItem; + } + else { + kdDebug() << "(K3bDataDoc) wrong tag in files-section: " << elem.nodeName() << endl; + return false; + } + + // load the sort weight + if( newItem ) + newItem->setSortWeight( elem.attribute( "sort_weight", "0" ).toInt() ); + + return true; +} + + +bool K3bDataDoc::saveDocumentData( QDomElement* docElem ) +{ + QDomDocument doc = docElem->ownerDocument(); + + saveGeneralDocumentData( docElem ); + + // all options + // ---------------------------------------------------------------------- + QDomElement optionsElem = doc.createElement( "options" ); + saveDocumentDataOptions( optionsElem ); + docElem->appendChild( optionsElem ); + // ---------------------------------------------------------------------- + + // the header stuff + // ---------------------------------------------------------------------- + QDomElement headerElem = doc.createElement( "header" ); + saveDocumentDataHeader( headerElem ); + docElem->appendChild( headerElem ); + + + // now do the "real" work: save the entries + // ---------------------------------------------------------------------- + QDomElement topElem = doc.createElement( "files" ); + + QPtrListIterator it( root()->children() ); + for( ; it.current(); ++it ) { + saveDataItem( it.current(), &doc, &topElem ); + } + + docElem->appendChild( topElem ); + // ---------------------------------------------------------------------- + + return true; +} + + +void K3bDataDoc::saveDocumentDataOptions( QDomElement& optionsElem ) +{ + QDomDocument doc = optionsElem.ownerDocument(); + + QDomElement topElem = doc.createElement( "rock_ridge" ); + topElem.setAttribute( "activated", isoOptions().createRockRidge() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "joliet" ); + topElem.setAttribute( "activated", isoOptions().createJoliet() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "udf" ); + topElem.setAttribute( "activated", isoOptions().createUdf() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "joliet_allow_103_characters" ); + topElem.setAttribute( "activated", isoOptions().jolietLong() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_allow_lowercase" ); + topElem.setAttribute( "activated", isoOptions().ISOallowLowercase() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_allow_period_at_begin" ); + topElem.setAttribute( "activated", isoOptions().ISOallowPeriodAtBegin() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_allow_31_char" ); + topElem.setAttribute( "activated", isoOptions().ISOallow31charFilenames() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_omit_version_numbers" ); + topElem.setAttribute( "activated", isoOptions().ISOomitVersionNumbers() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_omit_trailing_period" ); + topElem.setAttribute( "activated", isoOptions().ISOomitTrailingPeriod() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_max_filename_length" ); + topElem.setAttribute( "activated", isoOptions().ISOmaxFilenameLength() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_relaxed_filenames" ); + topElem.setAttribute( "activated", isoOptions().ISOrelaxedFilenames() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_no_iso_translate" ); + topElem.setAttribute( "activated", isoOptions().ISOnoIsoTranslate() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_allow_multidot" ); + topElem.setAttribute( "activated", isoOptions().ISOallowMultiDot() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_untranslated_filenames" ); + topElem.setAttribute( "activated", isoOptions().ISOuntranslatedFilenames() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "follow_symbolic_links" ); + topElem.setAttribute( "activated", isoOptions().followSymbolicLinks() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "create_trans_tbl" ); + topElem.setAttribute( "activated", isoOptions().createTRANS_TBL() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "hide_trans_tbl" ); + topElem.setAttribute( "activated", isoOptions().hideTRANS_TBL() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "iso_level" ); + topElem.appendChild( doc.createTextNode( QString::number(isoOptions().ISOLevel()) ) ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "discard_symlinks" ); + topElem.setAttribute( "activated", isoOptions().discardSymlinks() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "discard_broken_symlinks" ); + topElem.setAttribute( "activated", isoOptions().discardBrokenSymlinks() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "preserve_file_permissions" ); + topElem.setAttribute( "activated", isoOptions().preserveFilePermissions() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "force_input_charset" ); + topElem.setAttribute( "activated", isoOptions().forceInputCharset() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "do_not_cache_inodes" ); + topElem.setAttribute( "activated", isoOptions().doNotCacheInodes() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "input_charset" ); + topElem.appendChild( doc.createTextNode( isoOptions().inputCharset() ) ); + optionsElem.appendChild( topElem ); + + + topElem = doc.createElement( "whitespace_treatment" ); + switch( isoOptions().whiteSpaceTreatment() ) { + case K3bIsoOptions::strip: + topElem.appendChild( doc.createTextNode( "strip" ) ); + break; + case K3bIsoOptions::extended: + topElem.appendChild( doc.createTextNode( "extended" ) ); + break; + case K3bIsoOptions::replace: + topElem.appendChild( doc.createTextNode( "replace" ) ); + break; + default: + topElem.appendChild( doc.createTextNode( "noChange" ) ); + break; + } + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "whitespace_replace_string" ); + topElem.appendChild( doc.createTextNode( isoOptions().whiteSpaceTreatmentReplaceString() ) ); + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "data_track_mode" ); + if( m_dataMode == K3b::MODE1 ) + topElem.appendChild( doc.createTextNode( "mode1" ) ); + else if( m_dataMode == K3b::MODE2 ) + topElem.appendChild( doc.createTextNode( "mode2" ) ); + else + topElem.appendChild( doc.createTextNode( "auto" ) ); + optionsElem.appendChild( topElem ); + + + // save multisession + topElem = doc.createElement( "multisession" ); + switch( m_multisessionMode ) { + case START: + topElem.appendChild( doc.createTextNode( "start" ) ); + break; + case CONTINUE: + topElem.appendChild( doc.createTextNode( "continue" ) ); + break; + case FINISH: + topElem.appendChild( doc.createTextNode( "finish" ) ); + break; + case NONE: + topElem.appendChild( doc.createTextNode( "none" ) ); + break; + default: + topElem.appendChild( doc.createTextNode( "auto" ) ); + break; + } + optionsElem.appendChild( topElem ); + + topElem = doc.createElement( "verify_data" ); + topElem.setAttribute( "activated", verifyData() ? "yes" : "no" ); + optionsElem.appendChild( topElem ); + // ---------------------------------------------------------------------- +} + + +void K3bDataDoc::saveDocumentDataHeader( QDomElement& headerElem ) +{ + QDomDocument doc = headerElem.ownerDocument(); + + QDomElement topElem = doc.createElement( "volume_id" ); + topElem.appendChild( doc.createTextNode( isoOptions().volumeID() ) ); + headerElem.appendChild( topElem ); + + topElem = doc.createElement( "volume_set_id" ); + topElem.appendChild( doc.createTextNode( isoOptions().volumeSetId() ) ); + headerElem.appendChild( topElem ); + + topElem = doc.createElement( "volume_set_size" ); + topElem.appendChild( doc.createTextNode( QString::number(isoOptions().volumeSetSize()) ) ); + headerElem.appendChild( topElem ); + + topElem = doc.createElement( "volume_set_number" ); + topElem.appendChild( doc.createTextNode( QString::number(isoOptions().volumeSetNumber()) ) ); + headerElem.appendChild( topElem ); + + topElem = doc.createElement( "system_id" ); + topElem.appendChild( doc.createTextNode( isoOptions().systemId() ) ); + headerElem.appendChild( topElem ); + + topElem = doc.createElement( "application_id" ); + topElem.appendChild( doc.createTextNode( isoOptions().applicationID() ) ); + headerElem.appendChild( topElem ); + + topElem = doc.createElement( "publisher" ); + topElem.appendChild( doc.createTextNode( isoOptions().publisher() ) ); + headerElem.appendChild( topElem ); + + topElem = doc.createElement( "preparer" ); + topElem.appendChild( doc.createTextNode( isoOptions().preparer() ) ); + headerElem.appendChild( topElem ); + // ---------------------------------------------------------------------- +} + + +void K3bDataDoc::saveDataItem( K3bDataItem* item, QDomDocument* doc, QDomElement* parent ) +{ + if( K3bFileItem* fileItem = dynamic_cast( item ) ) { + if( m_oldSession.contains( fileItem ) ) { + kdDebug() << "(K3bDataDoc) ignoring fileitem " << fileItem->k3bName() << " from old session while saving..." << endl; + } + else { + QDomElement topElem = doc->createElement( "file" ); + topElem.setAttribute( "name", fileItem->k3bName() ); + QDomElement subElem = doc->createElement( "url" ); + subElem.appendChild( doc->createTextNode( fileItem->localPath() ) ); + topElem.appendChild( subElem ); + + if( item->sortWeight() != 0 ) + topElem.setAttribute( "sort_weight", QString::number(item->sortWeight()) ); + + parent->appendChild( topElem ); + + // add boot options as attributes to preserve compatibility to older K3b versions + if( K3bBootItem* bootItem = dynamic_cast( fileItem ) ) { + if( bootItem->imageType() == K3bBootItem::FLOPPY ) + topElem.setAttribute( "bootimage", "floppy" ); + else if( bootItem->imageType() == K3bBootItem::HARDDISK ) + topElem.setAttribute( "bootimage", "harddisk" ); + else + topElem.setAttribute( "bootimage", "none" ); + + topElem.setAttribute( "no_boot", bootItem->noBoot() ? "yes" : "no" ); + topElem.setAttribute( "boot_info_table", bootItem->bootInfoTable() ? "yes" : "no" ); + topElem.setAttribute( "load_segment", QString::number( bootItem->loadSegment() ) ); + topElem.setAttribute( "load_size", QString::number( bootItem->loadSize() ) ); + } + } + } + else if( item == m_bootCataloge ) { + QDomElement topElem = doc->createElement( "special" ); + topElem.setAttribute( "name", m_bootCataloge->k3bName() ); + topElem.setAttribute( "type", "boot cataloge" ); + + parent->appendChild( topElem ); + } + else if( K3bDirItem* dirItem = dynamic_cast( item ) ) { + QDomElement topElem = doc->createElement( "directory" ); + topElem.setAttribute( "name", dirItem->k3bName() ); + + if( item->sortWeight() != 0 ) + topElem.setAttribute( "sort_weight", QString::number(item->sortWeight()) ); + + QPtrListIterator it( dirItem->children() ); + for( ; it.current(); ++it ) { + saveDataItem( it.current(), doc, &topElem ); + } + + parent->appendChild( topElem ); + } +} + + +void K3bDataDoc::removeItem( K3bDataItem* item ) +{ + if( !item ) + return; + + if( item->isRemoveable() ) { + delete item; + } + else + kdDebug() << "(K3bDataDoc) tried to remove non-removable entry!" << endl; +} + + +void K3bDataDoc::itemRemovedFromDir( K3bDirItem*, K3bDataItem* removedItem ) +{ + // update the project size + if( !removedItem->isFromOldSession() ) + m_sizeHandler->removeFile( removedItem ); + + // update the boot item list + if( removedItem->isBootItem() ) { + m_bootImages.removeRef( static_cast( removedItem ) ); + if( m_bootImages.isEmpty() ) { + delete m_bootCataloge; + m_bootCataloge = 0; + } + } + + emit itemRemoved( removedItem ); + emit changed(); +} + + +void K3bDataDoc::itemAddedToDir( K3bDirItem*, K3bDataItem* item ) +{ + // update the project size + if( !item->isFromOldSession() ) + m_sizeHandler->addFile( item ); + + // update the boot item list + if( item->isBootItem() ) + m_bootImages.append( static_cast( item ) ); + + emit itemAdded( item ); + emit changed(); +} + + +void K3bDataDoc::moveItem( K3bDataItem* item, K3bDirItem* newParent ) +{ + if( !item || !newParent ) { + kdDebug() << "(K3bDataDoc) item or parentitem was NULL while moving." << endl; + return; + } + + if( !item->isMoveable() ) { + kdDebug() << "(K3bDataDoc) item is not movable! " << endl; + return; + } + + item->reparent( newParent ); +} + + +void K3bDataDoc::moveItems( QPtrList itemList, K3bDirItem* newParent ) +{ + if( !newParent ) { + kdDebug() << "(K3bDataDoc) tried to move items to nowhere...!" << endl; + return; + } + + QPtrListIterator it( itemList ); + for( ; it.current(); ++it ) { + // check if newParent is subdir of item + if( K3bDirItem* dirItem = dynamic_cast( it.current() ) ) { + if( dirItem->isSubItem( newParent ) ) { + continue; + } + } + + if( it.current()->isMoveable() ) + it.current()->reparent( newParent ); + } +} + + +K3bBurnJob* K3bDataDoc::newBurnJob( K3bJobHandler* hdl, QObject* parent ) +{ + return new K3bDataJob( this, hdl, parent ); +} + + +QString K3bDataDoc::treatWhitespace( const QString& path ) +{ + + // TODO: + // It could happen that two files with different names + // will have the same name after the treatment + // Perhaps we should add a number at the end or something + // similar (s.a.) + + + if( isoOptions().whiteSpaceTreatment() != K3bIsoOptions::noChange ) { + QString result = path; + + if( isoOptions().whiteSpaceTreatment() == K3bIsoOptions::replace ) { + result.replace( ' ', isoOptions().whiteSpaceTreatmentReplaceString() ); + } + else if( isoOptions().whiteSpaceTreatment() == K3bIsoOptions::strip ) { + result.remove( ' ' ); + } + else if( isoOptions().whiteSpaceTreatment() == K3bIsoOptions::extended ) { + result.truncate(0); + for( uint i = 0; i < path.length(); i++ ) { + if( path[i] == ' ' ) { + if( path[i+1] != ' ' ) + result.append( path[++i].upper() ); + } + else + result.append( path[i] ); + } + } + + kdDebug() << "(K3bDataDoc) converted " << path << " to " << result << endl; + return result; + } + else + return path; +} + + +void K3bDataDoc::prepareFilenames() +{ + m_needToCutFilenames = false; + m_needToCutFilenameItems.clear(); + + // + // if joliet is used cut the names and rename if necessary + // 64 characters for standard joliet and 103 characters for long joliet names + // + // Rockridge supports the full 255 UNIX chars and in case Rockridge is disabled we leave + // it to mkisofs for now since handling all the options to alter the ISO9660 standard it just + // too much. + // + + K3bDataItem* item = root(); + unsigned int maxlen = ( isoOptions().jolietLong() ? 103 : 64 ); + while( (item = item->nextSibling()) ) { + item->setWrittenName( treatWhitespace( item->k3bName() ) ); + + if( isoOptions().createJoliet() && item->writtenName().length() > maxlen ) { + m_needToCutFilenames = true; + item->setWrittenName( K3b::cutFilename( item->writtenName(), maxlen ) ); + m_needToCutFilenameItems.append( item ); + } + + // TODO: check the Joliet charset + } + + // + // 3. check if a directory contains items with the same name + // + prepareFilenamesInDir( root() ); +} + + +void K3bDataDoc::prepareFilenamesInDir( K3bDirItem* dir ) +{ + if( !dir ) + return; + + QPtrList sortedChildren; + QPtrListIterator it( dir->children() ); + + for( it.toLast(); it.current(); --it ) { + K3bDataItem* item = it.current(); + + if( item->isDir() ) + prepareFilenamesInDir( dynamic_cast( item ) ); + + // insertion sort + unsigned int i = 0; + while( i < sortedChildren.count() && item->writtenName() > sortedChildren.at(i)->writtenName() ) + ++i; + + sortedChildren.insert( i, item ); + } + + + if( isoOptions().createJoliet() || isoOptions().createRockRidge() ) { + QPtrList sameNameList; + while( !sortedChildren.isEmpty() ) { + + sameNameList.clear(); + + do { + sameNameList.append( sortedChildren.first() ); + sortedChildren.removeFirst(); + } while( !sortedChildren.isEmpty() && + sortedChildren.first()->writtenName() == sameNameList.first()->writtenName() ); + + if( sameNameList.count() > 1 ) { + // now we need to rename the items + unsigned int maxlen = 255; + if( isoOptions().createJoliet() ) { + if( isoOptions().jolietLong() ) + maxlen = 103; + else + maxlen = 64; + } + + int cnt = 1; + for( QPtrListIterator it( sameNameList ); + it.current(); ++it ) { + it.current()->setWrittenName( K3b::appendNumberToFilename( it.current()->writtenName(), cnt++, maxlen ) ); + } + } + } + } +} + + +void K3bDataDoc::informAboutNotFoundFiles() +{ + if( !m_notFoundFiles.isEmpty() ) { + KMessageBox::informationList( qApp->activeWindow(), i18n("Could not find the following files:"), + m_notFoundFiles, i18n("Not Found") ); + m_notFoundFiles.clear(); + } + + if( !m_noPermissionFiles.isEmpty() ) { + KMessageBox::informationList( qApp->activeWindow(), i18n("No permission to read the following files:"), + m_noPermissionFiles, i18n("No Read Permission") ); + + m_noPermissionFiles.clear(); + } +} + + +void K3bDataDoc::setMultiSessionMode( K3bDataDoc::MultiSessionMode mode ) +{ + if( m_multisessionMode == NONE || m_multisessionMode == START ) + clearImportedSession(); + + m_multisessionMode = mode; +} + + +bool K3bDataDoc::importSession( K3bDevice::Device* device ) +{ + K3bDevice::DiskInfo diskInfo = device->diskInfo(); + // DVD+RW media is reported as non-appendable + if( !diskInfo.appendable() && + !(diskInfo.mediaType() & (K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_RW_OVWR)) ) + return false; + + K3bDevice::Toc toc = device->readToc(); + if( toc.isEmpty() || + toc.last().type() != K3bDevice::Track::DATA ) + return false; + + long startSec = toc.last().firstSector().lba(); + K3bIso9660 iso( device, startSec ); + + if( iso.open() ) { + // remove previously imported sessions + clearImportedSession(); + + // set multisession option + if( m_multisessionMode != FINISH && m_multisessionMode != AUTO ) + m_multisessionMode = CONTINUE; + + // since in iso9660 it is possible that two files share it's data + // simply summing the file sizes could result in wrong values + // that's why we use the size from the toc. This is more accurate + // anyway since there might be files overwritten or removed + m_oldSessionSize = toc.last().lastSector().mode1Bytes(); + + kdDebug() << "(K3bDataDoc) imported session size: " << KIO::convertSize(m_oldSessionSize) << endl; + + // the track size for DVD+RW media and DVD-RW Overwrite media has nothing to do with the filesystem + // size. in that case we need to use the filesystem's size (which is ok since it's one track anyway, + // no real multisession) + if( diskInfo.mediaType() & (K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_RW_OVWR) ) { + m_oldSessionSize = iso.primaryDescriptor().volumeSpaceSize + * iso.primaryDescriptor().logicalBlockSize; + } + + // import some former settings + m_isoOptions.setCreateRockRidge( iso.firstRRDirEntry() != 0 ); + m_isoOptions.setCreateJoliet( iso.firstJolietDirEntry() != 0 ); + m_isoOptions.setVolumeID( iso.primaryDescriptor().volumeId ); + // TODO: also import some other pd fields + + const K3bIso9660Directory* rootDir = iso.firstRRDirEntry(); + // Jörg Schilling says that it is impossible to import the joliet tree for multisession +// if( !rootDir ) +// rootDir = iso.firstJolietDirEntry(); + if( !rootDir ) + rootDir = iso.firstIsoDirEntry(); + + if( rootDir ) { + createSessionImportItems( rootDir, root() ); + emit changed(); + return true; + } + else { + kdDebug() << "(K3bDataDoc::importSession) Could not find primary volume desc." << endl; + return false; + } + } + else { + kdDebug() << "(K3bDataDoc) unable to read toc." << endl; + return false; + } +} + + +void K3bDataDoc::createSessionImportItems( const K3bIso9660Directory* importDir, K3bDirItem* parent ) +{ + Q_ASSERT(importDir); + QStringList entries = importDir->entries(); + entries.remove( "." ); + entries.remove( ".." ); + for( QStringList::const_iterator it = entries.begin(); + it != entries.end(); ++it ) { + const K3bIso9660Entry* entry = importDir->entry( *it ); + K3bDataItem* oldItem = parent->find( entry->name() ); + if( entry->isDirectory() ) { + K3bDirItem* dir = 0; + if( oldItem && oldItem->isDir() ) { + dir = (K3bDirItem*)oldItem; + } + else { + // we overwrite without warning! + if( oldItem ) + removeItem( oldItem ); + dir = new K3bDirItem( entry->name(), this, parent ); + } + + dir->setRemoveable(false); + dir->setRenameable(false); + dir->setMoveable(false); + dir->setHideable(false); + dir->setWriteToCd(false); + dir->setExtraInfo( i18n("From previous session") ); + m_oldSession.append( dir ); + + createSessionImportItems( static_cast(entry), dir ); + } + else { + const K3bIso9660File* file = static_cast(entry); + + // we overwrite without warning! + if( oldItem ) + removeItem( oldItem ); + + K3bSessionImportItem* item = new K3bSessionImportItem( file, this, parent ); + item->setExtraInfo( i18n("From previous session") ); + m_oldSession.append( item ); + } + } +} + + +void K3bDataDoc::clearImportedSession() +{ + // m_oldSessionSizeHandler->clear(); + m_oldSessionSize = 0; + m_oldSession.setAutoDelete(false); + K3bDataItem* item = m_oldSession.first(); + while( !m_oldSession.isEmpty() ) { + if( item == 0 ) + item = m_oldSession.first(); + + if( item->isDir() ) { + K3bDirItem* dir = (K3bDirItem*)item; + if( dir->numDirs() + dir->numFiles() == 0 ) { + // this imported dir is not needed anymore + // since it is empty + m_oldSession.remove(); + delete dir; + } + else { + for( QPtrListIterator it( dir->children() ); it.current(); ++it ) { + if( !m_oldSession.contains(it.current()) ) { + m_oldSession.remove(); + // now the dir becomes a totally normal dir + dir->setRemoveable(true); + dir->setRenameable(true); + dir->setMoveable(true); + dir->setHideable(true); + dir->setWriteToCd(true); + dir->setExtraInfo( "" ); + break; + } + } + } + } + else { + m_oldSession.remove(); + delete item; + } + + item = m_oldSession.next(); + } + + m_multisessionMode = AUTO; + + emit changed(); +} + + +K3bDirItem* K3bDataDoc::bootImageDir() +{ + K3bDataItem* b = m_root->find( "boot" ); + if( !b ) { + b = new K3bDirItem( "boot", this, m_root ); + setModified( true ); + } + + // if we cannot create the dir because there is a file named boot just use the root dir + if( !b->isDir() ) + return m_root; + else + return static_cast(b); +} + + +K3bBootItem* K3bDataDoc::createBootItem( const QString& filename, K3bDirItem* dir ) +{ + if( !dir ) + dir = bootImageDir(); + + K3bBootItem* boot = new K3bBootItem( filename, this, dir ); + + if( !m_bootCataloge ) + createBootCatalogeItem(dir); + + return boot; +} + + +K3bDataItem* K3bDataDoc::createBootCatalogeItem( K3bDirItem* dir ) +{ + if( !m_bootCataloge ) { + QString newName = "boot.catalog"; + int i = 0; + while( dir->alreadyInDirectory( "boot.catalog" ) ) { + ++i; + newName = QString( "boot%1.catalog" ).arg(i); + } + + K3bSpecialDataItem* b = new K3bSpecialDataItem( this, 0, dir, newName ); + m_bootCataloge = b; + m_bootCataloge->setRemoveable(false); + m_bootCataloge->setHideable(false); + m_bootCataloge->setWriteToCd(false); + m_bootCataloge->setExtraInfo( i18n("El Torito boot catalog file") ); + b->setMimeType( i18n("Boot catalog") ); + } + else + m_bootCataloge->reparent( dir ); + + return m_bootCataloge; +} + + +QValueList K3bDataDoc::findItemByLocalPath( const QString& path ) const +{ + Q_UNUSED( path ); + return QValueList(); +} + + +bool K3bDataDoc::sessionImported() const +{ + return !m_oldSession.isEmpty(); +} + +#include "k3bdatadoc.moc" diff --git a/libk3b/projects/datacd/k3bdatadoc.h b/libk3b/projects/datacd/k3bdatadoc.h new file mode 100644 index 0000000..e09177a --- /dev/null +++ b/libk3b/projects/datacd/k3bdatadoc.h @@ -0,0 +1,297 @@ +/* + * + * $Id: k3bdatadoc.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BDATADOC_H +#define K3BDATADOC_H + +#include +#include + +#include "k3bisooptions.h" + +#include +#include +#include + +#include +#include +#include "k3b_export.h" + +class K3bDataItem; +class K3bRootItem; +class K3bDirItem; +class K3bFileItem; +class K3bJob; +class K3bBootItem; +class K3bFileCompilationSizeHandler; + +class KProgressDialog; +//class K3bView; +class KConfig; +class QString; +class QStringList; +class QWidget; +class QDomDocument; +class QDomElement; +class K3bIso9660Directory; + +namespace K3bDevice { + class Device; + class DeviceHandler; +} + + +/** + *@author Sebastian Trueg + */ + +class LIBK3B_EXPORT K3bDataDoc : public K3bDoc +{ + Q_OBJECT + + public: + K3bDataDoc( QObject* parent = 0 ); + virtual ~K3bDataDoc(); + + virtual int type() const { return DATA; } + virtual QString typeString() const; + + virtual QString name() const; + + enum MultiSessionMode { + /** + * Let the K3bDataJob decide if to close the CD or not. + * The decision is based on the state of the inserted media + * (appendable/closed), the size of the project (will it fill + * up the CD?), and the free space on the inserted media. + */ + AUTO, + NONE, + START, + CONTINUE, + FINISH + }; + + K3bRootItem* root() const { return m_root; } + + virtual bool newDocument(); + virtual KIO::filesize_t size() const; + + /** + * This is used for multisession where size() also returnes the imported session's size + */ + virtual KIO::filesize_t burningSize() const; + virtual K3b::Msf length() const; + virtual K3b::Msf burningLength() const; + + /** + * Simply deletes the item if it is removable (meaning isRemovable() returns true. + * Be aware that you can remove items simply by deleting them even if isRemovable() + * returns false. + */ + void removeItem( K3bDataItem* item ); + + /** + * Simply calls reparent. + */ + void moveItem( K3bDataItem* item, K3bDirItem* newParent ); + void moveItems( QPtrList itemList, K3bDirItem* newParent ); + + K3bDirItem* addEmptyDir( const QString& name, K3bDirItem* parent ); + + QString treatWhitespace( const QString& ); + + virtual K3bBurnJob* newBurnJob( K3bJobHandler* hdl, QObject* parent = 0 ); + + MultiSessionMode multiSessionMode() const { return m_multisessionMode; } + void setMultiSessionMode( MultiSessionMode mode ); + + int dataMode() const { return m_dataMode; } + void setDataMode( int m ) { m_dataMode = m; } + + void setVerifyData( bool b ) { m_verifyData = b; } + bool verifyData() const { return m_verifyData; } + + static bool nameAlreadyInDir( const QString&, K3bDirItem* ); + + /** + * Most of the options that map to the mkisofs parameters are grouped + * together in the K3bIsoOptions class to allow easy saving to and loading + * from a KConfig object. + */ + const K3bIsoOptions& isoOptions() const { return m_isoOptions; } + void setIsoOptions( const K3bIsoOptions& ); + + const QPtrList& bootImages() { return m_bootImages; } + K3bDataItem* bootCataloge() { return m_bootCataloge; } + + K3bDirItem* bootImageDir(); + + /** + * Create a boot item and also create a boot cataloge file in case none + * exists in the project. + * + * Calling this method has the same effect like creating a new K3bBootItem + * instance manually and then calling createBootCatalogeItem. + * + * \return The new boot item on success or 0 in case a file with the same + * name already exists. + */ + K3bBootItem* createBootItem( const QString& filename, K3bDirItem* bootDir = 0 ); + + /** + * Create a new boot catalog item. + * For now this is not called automatically for internal reasons. + * + * Call this if you create boot items manually instead of using createBootItem. + * + * The boot catalog is automatically deleted once the last boot item is removed + * from the doc. + * + * \return The new boot catalog item or the old one if it already exists. + */ + K3bDataItem* createBootCatalogeItem( K3bDirItem* bootDir ); + + /** + * This will prepare the filenames as written to the image. + * These filenames are saved in K3bDataItem::writtenName + */ + void prepareFilenames(); + + /** + * Returns true if filenames need to be cut due to the limitations of Joliet. + * + * This is only valid after a call to @p prepareFilenames() + */ + bool needToCutFilenames() const { return m_needToCutFilenames; } + + const QValueList& needToCutFilenameItems() const { return m_needToCutFilenameItems; } + + /** + * Imports a session into the project. This will create K3bSessionImportItems + * and properly set the imported session size. + * Some settings will be adjusted to the imported session (joliet, rr). + * + * Be aware that this method is blocking. + * + * \return true if the old session was successfully imported, false if no + * session could be found. + * + * \see clearImportedSession() + */ + bool importSession( K3bDevice::Device* ); + + bool sessionImported() const; + + /** + * Searches for an item by it's local path. + * + * NOT IMPLEMENTED YET! + * + * \return The items that correspond to the specified local path. + */ + QValueList findItemByLocalPath( const QString& path ) const; + + public slots: + virtual void addUrls( const KURL::List& urls ); + + /** + * Add urls syncroneously + * This method adds files recursively including symlinks, hidden, and system files. + * If a file already exists the new file's name will be appended a number. + */ + virtual void addUrls( const KURL::List& urls, K3bDirItem* dir ); + + void clearImportedSession(); + + /** + * Just a convience method to prevent using setIsoOptions for this + * often used value. + */ + void setVolumeID( const QString& ); + + signals: + void itemRemoved( K3bDataItem* ); + void itemAdded( K3bDataItem* ); + + protected: + /** reimplemented from K3bDoc */ + virtual bool loadDocumentData( QDomElement* root ); + /** reimplemented from K3bDoc */ + virtual bool saveDocumentData( QDomElement* ); + + void saveDocumentDataOptions( QDomElement& optionsElem ); + void saveDocumentDataHeader( QDomElement& headerElem ); + bool loadDocumentDataOptions( QDomElement optionsElem ); + bool loadDocumentDataHeader( QDomElement optionsElem ); + + K3bFileCompilationSizeHandler* m_sizeHandler; + + // K3bFileCompilationSizeHandler* m_oldSessionSizeHandler; + KIO::filesize_t m_oldSessionSize; + + private: + void prepareFilenamesInDir( K3bDirItem* dir ); + void createSessionImportItems( const K3bIso9660Directory*, K3bDirItem* parent ); + + /** + * used by K3bDirItem to inform about removed items. + */ + void itemRemovedFromDir( K3bDirItem* parent, K3bDataItem* removedItem ); + void itemAddedToDir( K3bDirItem* parent, K3bDataItem* addedItem ); + + /** + * load recursivly + */ + bool loadDataItem( QDomElement& e, K3bDirItem* parent ); + /** + * save recursivly + */ + void saveDataItem( K3bDataItem* item, QDomDocument* doc, QDomElement* parent ); + + void informAboutNotFoundFiles(); + + QStringList m_notFoundFiles; + QStringList m_noPermissionFiles; + + K3bRootItem* m_root; + + int m_dataMode; + + bool m_verifyData; + + KIO::filesize_t m_size; + + K3bIsoOptions m_isoOptions; + + MultiSessionMode m_multisessionMode; + QPtrList m_oldSession; + + // boot cd stuff + K3bDataItem* m_bootCataloge; + QPtrList m_bootImages; + + bool m_bExistingItemsReplaceAll; + bool m_bExistingItemsIgnoreAll; + + bool m_needToCutFilenames; + QValueList m_needToCutFilenameItems; + + friend class K3bMixedDoc; + friend class K3bDirItem; +}; + +#endif diff --git a/libk3b/projects/datacd/k3bdataitem.cpp b/libk3b/projects/datacd/k3bdataitem.cpp new file mode 100644 index 0000000..6f2a861 --- /dev/null +++ b/libk3b/projects/datacd/k3bdataitem.cpp @@ -0,0 +1,264 @@ +/* + * + * $Id: k3bdataitem.cpp 659634 2007-04-30 14:51:32Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bdataitem.h" +#include "k3bdiritem.h" +#include "k3bdatadoc.h" +#include + +#include + + +class K3bDataItem::Private +{ +public: + int flags; +}; + + +K3bDataItem::K3bDataItem( K3bDataDoc* doc, K3bDataItem* parent, int flags ) + : m_bHideOnRockRidge(false), + m_bHideOnJoliet(false), + m_bRemoveable(true), + m_bRenameable(true), + m_bMovable(true), + m_bHideable(true), + m_bWriteToCd(true), + m_sortWeight(0) +{ + d = new Private; + d->flags = flags; + + m_doc = doc; + m_bHideOnRockRidge = m_bHideOnJoliet = false; + + if( parent ) + m_parentDir = parent->getDirItem(); + else + m_parentDir = 0; +} + + +K3bDataItem::K3bDataItem( const K3bDataItem& item ) + : m_k3bName( item.m_k3bName ), + m_doc( 0 ), + m_parentDir( 0 ), + m_bHideOnRockRidge( item.m_bHideOnRockRidge ), + m_bHideOnJoliet( item.m_bHideOnJoliet ), + m_bRemoveable( item.m_bRemoveable ), + m_bRenameable( item.m_bRenameable ), + m_bMovable( item.m_bMovable ), + m_bHideable( item.m_bHideable ), + m_bWriteToCd( item.m_bWriteToCd ), + m_extraInfo( item.m_extraInfo ), + m_sortWeight( item.m_sortWeight ) +{ + d = new Private; + d->flags = item.d->flags; +} + + +K3bDataItem::~K3bDataItem() +{ + delete d; +} + + +void K3bDataItem::setFlags( int flags ) +{ + d->flags = flags; +} + + +bool K3bDataItem::isBootItem() const +{ + return d->flags & BOOT_IMAGE; +} + + +KIO::filesize_t K3bDataItem::size() const +{ + return itemSize( m_doc + ? m_doc->isoOptions().followSymbolicLinks() || + !m_doc->isoOptions().createRockRidge() + : false ); +} + + +K3b::Msf K3bDataItem::blocks() const +{ + return itemBlocks( m_doc + ? m_doc->isoOptions().followSymbolicLinks() || + !m_doc->isoOptions().createRockRidge() + : false ); +} + + +K3b::Msf K3bDataItem::itemBlocks( bool followSymbolicLinks ) const +{ + return (long)::ceil( (double)itemSize( followSymbolicLinks ) / 2048.0 ); +} + + +void K3bDataItem::setK3bName( const QString& name ) { + if ( name != m_k3bName ) { + // test for not-allowed characters + if( name.contains('/') ) { + kdDebug() << "(K3bDataItem) name contained invalid characters!" << endl; + return; + } + + if( parent() ) { + K3bDataItem* item = parent()->find( name ); + if( item && item != this ) { + kdDebug() << "(K3bDataItem) item with that name already exists." << endl; + return; + } + } + + m_k3bName = name; + m_doc->setModified(); +} +} + + +const QString& K3bDataItem::k3bName() const +{ + return m_k3bName; +} + + +K3bDataItem* K3bDataItem::take() +{ + if( parent() ) + parent()->takeDataItem( this ); + + return this; +} + + +QString K3bDataItem::k3bPath() const +{ + if( !getParent() ) + return QString::null; // the root item is the only one not having a parent + else if( isDir() ) + return getParent()->k3bPath() + k3bName() + "/"; + else + return getParent()->k3bPath() + k3bName(); +} + + +QString K3bDataItem::writtenPath() const +{ + if( !getParent() ) + return QString::null; // the root item is the only one not having a parent + else if( isDir() ) + return getParent()->writtenPath() + writtenName() + "/"; + else + return getParent()->writtenPath() + writtenName(); +} + + +QString K3bDataItem::iso9660Path() const +{ + if( !getParent() ) + return QString::null; // the root item is the only one not having a parent + else if( isDir() ) + return getParent()->iso9660Path() + iso9660Name() + "/"; + else + return getParent()->iso9660Path() + iso9660Name(); +} + + +K3bDataItem* K3bDataItem::nextSibling() const +{ + K3bDataItem* item = const_cast(this); // urg, but we know that we don't mess with it, so... + K3bDirItem* parentItem = getParent(); + + while( parentItem ) { + if( K3bDataItem* i = parentItem->nextChild( item ) ) + return i; + + item = parentItem; + parentItem = item->getParent(); + } + + return 0; +} + + +void K3bDataItem::reparent( K3bDirItem* newParent ) +{ + // addDataItem will do all the stuff including taking this + newParent->addDataItem( this ); +} + + +bool K3bDataItem::hideOnRockRidge() const +{ + if( !isHideable() ) + return false; + if( getParent() ) + return m_bHideOnRockRidge || getParent()->hideOnRockRidge(); + else + return m_bHideOnRockRidge; +} + + +bool K3bDataItem::hideOnJoliet() const +{ + if( !isHideable() ) + return false; + if( getParent() ) + return m_bHideOnJoliet || getParent()->hideOnJoliet(); + else + return m_bHideOnJoliet; +} + + +void K3bDataItem::setHideOnRockRidge( bool b ) +{ + // there is no use in changing the value if + // it is already set by the parent + if( ( !getParent() || !getParent()->hideOnRockRidge() ) && + b != m_bHideOnRockRidge ) { + m_bHideOnRockRidge = b; + if ( m_doc ) + m_doc->setModified(); +} +} + + +void K3bDataItem::setHideOnJoliet( bool b ) +{ + // there is no use in changing the value if + // it is already set by the parent + if( ( !getParent() || !getParent()->hideOnJoliet() ) && + b != m_bHideOnJoliet ) { + m_bHideOnJoliet = b; + if ( m_doc ) + m_doc->setModified(); +} +} + + +int K3bDataItem::depth() const +{ + if( getParent() ) + return getParent()->depth() + 1; + else + return 0; +} diff --git a/libk3b/projects/datacd/k3bdataitem.h b/libk3b/projects/datacd/k3bdataitem.h new file mode 100644 index 0000000..36cdf05 --- /dev/null +++ b/libk3b/projects/datacd/k3bdataitem.h @@ -0,0 +1,225 @@ +/* + * + * $Id: k3bdataitem.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BDATAITEM_H +#define K3BDATAITEM_H + + +class K3bDirItem; +class K3bDataDoc; + +#include + +#include + +#include +#include "k3b_export.h" + + +/** + *@author Sebastian Trueg + */ +class LIBK3B_EXPORT K3bDataItem +{ + public: + K3bDataItem( K3bDataDoc* doc, K3bDataItem* parent = 0, int flags = 0 ); + + /** + * Default copy constructor. + * + * The result is an exact copy except that no parent dir it set and, thus, also no doc. + */ + K3bDataItem( const K3bDataItem& ); + + virtual ~K3bDataItem(); + + /** + * Return an exact copy of this data item. + * + * The result is an exact copy except that no parent dir it set and, thus, also no doc. + * + * Implementations should use the default constructor. + */ + virtual K3bDataItem* copy() const = 0; + + K3bDirItem* parent() { return m_parentDir; } + K3bDirItem* getParent() const { return m_parentDir; } + + /** + * Remove this item from it's parent and return a pointer to it. + */ + K3bDataItem* take(); + + K3bDataDoc* doc() const { return m_doc; } + virtual const QString& k3bName() const; + virtual void setK3bName( const QString& ); + + /** + * returns the path as defined by the k3b-hierachy, NOT starting with a slash + * (since this is used for graft-points!) + * directories have a trailing "/" + */ + virtual QString k3bPath() const; + + /** + * Returns the name of the item as used on the CD or DVD image. + * + * This is only valid after a call to @p K3bDataDoc::prepareFilenames() + */ + const QString& writtenName() const { return m_writtenName; } + + /** + * \return the pure name used in the Iso9660 tree. + * + * This is only valid after a call to @p K3bDataDoc::prepareFilenames() + */ + const QString& iso9660Name() const { return m_rawIsoName; } + + /** + * Returns the path of the item as written to the CD or DVD image. + * + * This is suited to be used for mkisofs graftpoints. + * + * This is only valid after a call to @p K3bDataDoc::prepareFilenames() + */ + virtual QString writtenPath() const; + + virtual QString iso9660Path() const; + + /** + * Used to set the written name by @p K3bDataDoc::prepareFilenames() + */ + void setWrittenName( const QString& s ) { m_writtenName = s; } + + /** + * Used to set the pure Iso9660 name by @p K3bDataDoc::prepareFilenames() + */ + void setIso9660Name( const QString& s ) { m_rawIsoName = s; } + + virtual K3bDataItem* nextSibling() const; + + /** returns the path to the file on the local filesystem */ + virtual QString localPath() const { return QString::null; } + + /** + * The size of the item + */ + KIO::filesize_t size() const; + + /** + * \return The number of blocks (2048 bytes) occupied by this item. + * This value equals to ceil(size()/2048) + */ + K3b::Msf blocks() const; + + /** + * \returne the dir of the item (or the item itself if it is a dir) + */ + virtual K3bDirItem* getDirItem() const { return getParent(); } + + virtual void reparent( K3bDirItem* ); + + // FIXME: use all these flags and make the isXXX methods + // non-virtual. Then move the parent()->addDataItem call + // to the K3bDataItem constructor + enum ItemFlags { + DIR = 0x1, + FILE = 0x2, + SPECIALFILE = 0x4, + SYMLINK = 0x8, + OLD_SESSION = 0x10, + BOOT_IMAGE = 0x11 + }; + + int flags() const; + + virtual bool isDir() const { return false; } + virtual bool isFile() const { return false; } + virtual bool isSpecialFile() const { return false; } + virtual bool isSymLink() const { return false; } + virtual bool isFromOldSession() const { return false; } + bool isBootItem() const; + + bool hideOnRockRidge() const; + bool hideOnJoliet() const; + + virtual void setHideOnRockRidge( bool b ); + virtual void setHideOnJoliet( bool b ); + + virtual long sortWeight() const { return m_sortWeight; } + virtual void setSortWeight( long w ) { m_sortWeight = w; } + + virtual int depth() const; + + virtual bool isValid() const { return true; } + + // these are all needed for special fileitems like + // imported sessions or the movix filesystem + virtual bool isRemoveable() const { return m_bRemoveable; } + virtual bool isMoveable() const { return m_bMovable; } + virtual bool isRenameable() const { return m_bRenameable; } + virtual bool isHideable() const { return m_bHideable; } + virtual bool writeToCd() const { return m_bWriteToCd; } + virtual const QString& extraInfo() const { return m_extraInfo; } + + void setRenameable( bool b ) { m_bRenameable = b; } + void setMoveable( bool b ) { m_bMovable = b; } + void setRemoveable( bool b ) { m_bRemoveable = b; } + void setHideable( bool b ) { m_bHideable = b; } + void setWriteToCd( bool b ) { m_bWriteToCd = b; } + void setExtraInfo( const QString& i ) { m_extraInfo = i; } + + protected: + virtual KIO::filesize_t itemSize( bool followSymlinks ) const = 0; + + /** + * \param followSymlinks If true symlinks will be followed and their + * size equals the size of the file they are + * pointing to. + * + * \return The number of blocks (2048 bytes) occupied by this item. + */ + virtual K3b::Msf itemBlocks( bool followSymlinks ) const; + + QString m_k3bName; + + void setFlags( int flags ); + + private: + class Private; + Private* d; + + QString m_writtenName; + QString m_rawIsoName; + + K3bDataDoc* m_doc; + K3bDirItem* m_parentDir; + + bool m_bHideOnRockRidge; + bool m_bHideOnJoliet; + bool m_bRemoveable; + bool m_bRenameable; + bool m_bMovable; + bool m_bHideable; + bool m_bWriteToCd; + QString m_extraInfo; + + long m_sortWeight; + + friend class K3bDirItem; +}; + +#endif diff --git a/libk3b/projects/datacd/k3bdatajob.cpp b/libk3b/projects/datacd/k3bdatajob.cpp new file mode 100644 index 0000000..7009a43 --- /dev/null +++ b/libk3b/projects/datacd/k3bdatajob.cpp @@ -0,0 +1,972 @@ +/* + * + * $Id: k3bdatajob.cpp 690187 2007-07-20 09:18:03Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bdatajob.h" +#include "k3bdatadoc.h" +#include "k3bisoimager.h" +#include "k3bmsinfofetcher.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + + +class K3bDataJob::Private +{ +public: + Private() + : usedWritingApp(K3b::CDRECORD), + verificationJob(0) { + } + + K3bDataDoc* doc; + + bool initializingImager; + bool imageFinished; + bool canceled; + + KTempFile* tocFile; + + int usedDataMode; + int usedWritingApp; + int usedWritingMode; + K3bDataDoc::MultiSessionMode usedMultiSessionMode; + + int copies; + int copiesDone; + + K3bVerificationJob* verificationJob; + + K3bFileSplitter imageFile; + K3bActivePipe pipe; +}; + + +K3bDataJob::K3bDataJob( K3bDataDoc* doc, K3bJobHandler* hdl, QObject* parent ) + : K3bBurnJob( hdl, parent ) +{ + d = new Private; + + d->doc = doc; + m_writerJob = 0; + d->tocFile = 0; + + m_isoImager = 0; + + m_msInfoFetcher = new K3bMsInfoFetcher( this, this ); + connect( m_msInfoFetcher, SIGNAL(finished(bool)), this, SLOT(slotMsInfoFetched(bool)) ); + connect( m_msInfoFetcher, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_msInfoFetcher, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + + d->imageFinished = true; +} + +K3bDataJob::~K3bDataJob() +{ + delete d->tocFile; + delete d; +} + + +K3bDoc* K3bDataJob::doc() const +{ + return d->doc; +} + + +K3bDevice::Device* K3bDataJob::writer() const +{ + if( doc()->onlyCreateImages() ) + return 0; // no writer needed -> no blocking on K3bBurnJob + else + return doc()->burner(); +} + + +void K3bDataJob::start() +{ + jobStarted(); + + d->canceled = false; + d->imageFinished = false; + d->copies = d->doc->copies(); + d->copiesDone = 0; + d->usedMultiSessionMode = d->doc->multiSessionMode(); + + prepareImager(); + + if( d->doc->dummy() ) { + d->doc->setVerifyData( false ); + d->copies = 1; + } + + emit newTask( i18n("Preparing data") ); + + // there is no harm in setting these even if we write on-the-fly + d->imageFile.setName( d->doc->tempDir() ); + d->pipe.readFromIODevice( &d->imageFile ); + + if( d->usedMultiSessionMode == K3bDataDoc::AUTO && !d->doc->onlyCreateImages() ) + determineMultiSessionMode(); + else + prepareWriting(); +} + + +void K3bDataJob::prepareWriting() +{ + if( !d->doc->onlyCreateImages() && + ( d->usedMultiSessionMode == K3bDataDoc::CONTINUE || + d->usedMultiSessionMode == K3bDataDoc::FINISH ) ) { + // no sense continuing the same session twice + // FIXME: why not? + d->copies = 1; + + m_msInfoFetcher->setDevice( d->doc->burner() ); + + if( !waitForMedium() ) { + cancel(); + return; + } + + if( K3b::isMounted( d->doc->burner() ) ) { + emit infoMessage( i18n("Unmounting disk"), INFO ); + K3b::unmount( d->doc->burner() ); + } + + m_msInfoFetcher->start(); + } + else { + m_isoImager->setMultiSessionInfo( QString::null ); + prepareData(); + + d->initializingImager = true; + m_isoImager->init(); + } +} + + +void K3bDataJob::slotMsInfoFetched(bool success) +{ + if( success ) { + // we call this here since in ms mode we might want to check + // the last track's datamode + prepareData(); + + if( d->usedWritingApp == K3b::CDRDAO ) // cdrdao seems to write a 150 blocks pregap that is not used by cdrecord + m_isoImager->setMultiSessionInfo( QString("%1,%2").arg(m_msInfoFetcher->lastSessionStart()).arg(m_msInfoFetcher->nextSessionStart()+150), d->doc->burner() ); + else + m_isoImager->setMultiSessionInfo( m_msInfoFetcher->msInfo(), d->doc->burner() ); + + d->initializingImager = true; + m_isoImager->init(); + } + else { + // the MsInfoFetcher already emitted failure info + cancelAll(); + jobFinished( false ); + } +} + + +void K3bDataJob::writeImage() +{ + d->initializingImager = false; + + emit burning(false); + + // get image file path + if( d->doc->tempDir().isEmpty() ) + d->doc->setTempDir( K3b::findUniqueFilePrefix( d->doc->isoOptions().volumeID() ) + ".iso" ); + + // TODO: check if the image file is part of the project and if so warn the user + // and append some number to make the path unique. + + emit newTask( i18n("Creating image file") ); + emit newSubTask( i18n("Track 1 of 1") ); + emit infoMessage( i18n("Creating image file in %1").arg(d->doc->tempDir()), INFO ); + + m_isoImager->writeToImageFile( d->doc->tempDir() ); + m_isoImager->start(); +} + + +bool K3bDataJob::startOnTheFlyWriting() +{ + if( prepareWriterJob() ) { + if( startWriterJob() ) { + // try a direct connection between the processes + if( m_writerJob->fd() != -1 ) + m_isoImager->writeToFd( m_writerJob->fd() ); + d->initializingImager = false; + m_isoImager->start(); + return true; + } + } + return false; +} + + +void K3bDataJob::cancel() +{ + emit infoMessage( i18n("Writing canceled."), K3bJob::ERROR ); + emit canceled(); + + if( m_writerJob && m_writerJob->active() ) { + // + // lets wait for the writer job to finish + // and let it finish the job for good. + // + cancelAll(); + } + else { + // + // Just cancel all and return + // This is bad design as we should wait for all subjobs to finish + // + cancelAll(); + jobFinished( false ); + } +} + + +void K3bDataJob::slotIsoImagerPercent( int p ) +{ + if( d->doc->onlyCreateImages() ) { + emit subPercent( p ); + emit percent( p ); + } + else if( !d->doc->onTheFly() ) { + double totalTasks = d->copies; + double tasksDone = d->copiesDone; // =0 when creating an image + if( d->doc->verifyData() ) { + totalTasks*=2; + tasksDone*=2; + } + if( !d->doc->onTheFly() ) { + totalTasks+=1.0; + } + + emit subPercent( p ); + emit percent( (int)((100.0*tasksDone + (double)p) / totalTasks) ); + } +} + + +void K3bDataJob::slotIsoImagerFinished( bool success ) +{ + if( d->initializingImager ) { + if( success ) { + if( d->doc->onTheFly() && !d->doc->onlyCreateImages() ) { + if( !startOnTheFlyWriting() ) { + cancelAll(); + jobFinished( false ); + } + } + else { + writeImage(); + } + } + else { + if( m_isoImager->hasBeenCanceled() ) + emit canceled(); + jobFinished( false ); + } + } + else { + // tell the writer that there won't be more data + if( d->doc->onTheFly() && m_writerJob ) + m_writerJob->closeFd(); + + if( !d->doc->onTheFly() || + d->doc->onlyCreateImages() ) { + + if( success ) { + emit infoMessage( i18n("Image successfully created in %1").arg(d->doc->tempDir()), K3bJob::SUCCESS ); + d->imageFinished = true; + + if( d->doc->onlyCreateImages() ) { + jobFinished( true ); + } + else { + if( prepareWriterJob() ) { + startWriterJob(); + d->pipe.writeToFd( m_writerJob->fd(), true ); + d->pipe.open(true); + } + } + } + else { + if( m_isoImager->hasBeenCanceled() ) + emit canceled(); + else + emit infoMessage( i18n("Error while creating ISO image"), ERROR ); + + cancelAll(); + jobFinished( false ); + } + } + else if( !success ) { // on-the-fly + // + // In case the imager failed let's make sure the writer does not emit an unusable + // error message. + // + if( m_writerJob && m_writerJob->active() ) + m_writerJob->setSourceUnreadable( true ); + + // there is one special case which we need to handle here: the iso imager might be canceled + // FIXME: the iso imager should not be able to cancel itself + if( m_isoImager->hasBeenCanceled() && !this->hasBeenCanceled() ) + cancel(); + } + } +} + + +bool K3bDataJob::startWriterJob() +{ + if( d->doc->dummy() ) + emit newTask( i18n("Simulating") ); + else if( d->copies > 1 ) + emit newTask( i18n("Writing Copy %1").arg(d->copiesDone+1) ); + else + emit newTask( i18n("Writing") ); + + // if we append a new session we asked for an appendable cd already + if( d->usedMultiSessionMode == K3bDataDoc::NONE || + d->usedMultiSessionMode == K3bDataDoc::START ) { + + if( !waitForMedium() ) { + return false; + } + } + + emit burning(true); + m_writerJob->start(); + return true; +} + + +void K3bDataJob::slotWriterJobPercent( int p ) +{ + double totalTasks = d->copies; + double tasksDone = d->copiesDone; + if( d->doc->verifyData() ) { + totalTasks*=2; + tasksDone*=2; + } + if( !d->doc->onTheFly() ) { + totalTasks+=1.0; + tasksDone+=1.0; + } + + emit percent( (int)((100.0*tasksDone + (double)p) / totalTasks) ); +} + + +void K3bDataJob::slotWriterNextTrack( int t, int tt ) +{ + emit newSubTask( i18n("Writing Track %1 of %2").arg(t).arg(tt) ); +} + + +void K3bDataJob::slotWriterJobFinished( bool success ) +{ + d->pipe.close(); + + // + // This is a little workaround for the bad cancellation handling in this job + // see cancel() + // + if( d->canceled ) { + if( active() ) + jobFinished( false ); + } + + if( success ) { + // allright + // the writerJob should have emited the "simulation/writing successful" signal + + if( d->doc->verifyData() ) { + if( !d->verificationJob ) { + d->verificationJob = new K3bVerificationJob( this, this ); + connect( d->verificationJob, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + connect( d->verificationJob, SIGNAL(newTask(const QString&)), + this, SIGNAL(newSubTask(const QString&)) ); + connect( d->verificationJob, SIGNAL(newSubTask(const QString&)), + this, SIGNAL(newSubTask(const QString&)) ); + connect( d->verificationJob, SIGNAL(percent(int)), + this, SLOT(slotVerificationProgress(int)) ); + connect( d->verificationJob, SIGNAL(percent(int)), + this, SIGNAL(subPercent(int)) ); + connect( d->verificationJob, SIGNAL(finished(bool)), + this, SLOT(slotVerificationFinished(bool)) ); + connect( d->verificationJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + + } + d->verificationJob->clear(); + d->verificationJob->setDevice( d->doc->burner() ); + d->verificationJob->setGrownSessionSize( m_isoImager->size() ); + d->verificationJob->addTrack( 0, m_isoImager->checksum(), m_isoImager->size() ); + + emit burning(false); + + emit newTask( i18n("Verifying written data") ); + + d->verificationJob->start(); + } + else { + d->copiesDone++; + + if( d->copiesDone < d->copies ) { + K3bDevice::eject( d->doc->burner() ); + + bool failed = false; + if( d->doc->onTheFly() ) + failed = !startOnTheFlyWriting(); + else + failed = !startWriterJob(); + + if( failed ) { + cancel(); + } + else if( !d->doc->onTheFly() ) { + d->pipe.writeToFd( m_writerJob->fd(), true ); + d->pipe.open(true); + } + } + else { + cleanup(); + jobFinished(true); + } + } + } + else { + cancelAll(); + jobFinished( false ); + } +} + + +void K3bDataJob::slotVerificationProgress( int p ) +{ + double totalTasks = d->copies*2; + double tasksDone = d->copiesDone*2 + 1; // the writing of the current copy has already been finished + + if( !d->doc->onTheFly() ) { + totalTasks+=1.0; + tasksDone+=1.0; + } + + emit percent( (int)((100.0*tasksDone + (double)p) / totalTasks) ); +} + + +void K3bDataJob::slotVerificationFinished( bool success ) +{ + d->copiesDone++; + + // reconnect our imager which we deconnected for the verification + connectImager(); + + if( k3bcore->globalSettings()->ejectMedia() || d->copiesDone < d->copies ) + K3bDevice::eject( d->doc->burner() ); + + if( !d->canceled && d->copiesDone < d->copies ) { + bool failed = false; + if( d->doc->onTheFly() ) + failed = !startOnTheFlyWriting(); + else + failed = !startWriterJob(); + + if( failed ) + cancel(); + else if( !d->doc->onTheFly() ) { + d->pipe.writeToFd( m_writerJob->fd(), true ); + d->pipe.open(true); + } + } + else { + cleanup(); + jobFinished( success ); + } +} + + +void K3bDataJob::setWriterJob( K3bAbstractWriter* writer ) +{ + // FIXME: progressedsize for multiple copies + m_writerJob = writer; + connect( m_writerJob, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_writerJob, SIGNAL(percent(int)), this, SLOT(slotWriterJobPercent(int)) ); + connect( m_writerJob, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSize(int, int)) ); + connect( m_writerJob, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); + connect( m_writerJob, SIGNAL(processedSubSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( m_writerJob, SIGNAL(nextTrack(int, int)), this, SLOT(slotWriterNextTrack(int, int)) ); + connect( m_writerJob, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) ); + connect( m_writerJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); + connect( m_writerJob, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + connect( m_writerJob, SIGNAL(finished(bool)), this, SLOT(slotWriterJobFinished(bool)) ); + connect( m_writerJob, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_writerJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); +} + + +void K3bDataJob::setImager( K3bIsoImager* imager ) +{ + if( m_isoImager != imager ) { + delete m_isoImager; + + m_isoImager = imager; + + connectImager(); + } +} + + +void K3bDataJob::connectImager() +{ + m_isoImager->disconnect( this ); + connect( m_isoImager, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_isoImager, SIGNAL(percent(int)), this, SLOT(slotIsoImagerPercent(int)) ); + connect( m_isoImager, SIGNAL(finished(bool)), this, SLOT(slotIsoImagerFinished(bool)) ); + connect( m_isoImager, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); +} + + +void K3bDataJob::prepareImager() +{ + if( !m_isoImager ) + setImager( new K3bIsoImager( d->doc, this, this ) ); +} + + +bool K3bDataJob::prepareWriterJob() +{ + if( m_writerJob ) + return true; + + // It seems as if cdrecord is not able to append sessions in dao mode whereas cdrdao is + if( d->usedWritingApp == K3b::CDRECORD ) { + K3bCdrecordWriter* writer = new K3bCdrecordWriter( d->doc->burner(), this, this ); + + // cdrecord manpage says that "not all" writers are able to write + // multisession disks in dao mode. That means there are writers that can. + + // Does it really make sence to write DAta ms cds in DAO mode since writing the + // first session of a cd-extra in DAO mode is no problem with my writer while + // writing the second data session is only possible in TAO mode. + if( d->usedWritingMode == K3b::DAO && + d->usedMultiSessionMode != K3bDataDoc::NONE ) + emit infoMessage( i18n("Most writers do not support writing " + "multisession CDs in DAO mode."), INFO ); + + writer->setWritingMode( d->usedWritingMode ); + writer->setSimulate( d->doc->dummy() ); + writer->setBurnSpeed( d->doc->speed() ); + + // multisession + if( d->usedMultiSessionMode == K3bDataDoc::START || + d->usedMultiSessionMode == K3bDataDoc::CONTINUE ) { + writer->addArgument("-multi"); + } + + if( d->doc->onTheFly() && + ( d->usedMultiSessionMode == K3bDataDoc::CONTINUE || + d->usedMultiSessionMode == K3bDataDoc::FINISH ) ) + writer->addArgument("-waiti"); + + if( d->usedDataMode == K3b::MODE1 ) + writer->addArgument( "-data" ); + else { + if( k3bcore->externalBinManager()->binObject("cdrecord") && + k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "xamix" ) ) + writer->addArgument( "-xa" ); + else + writer->addArgument( "-xa1" ); + } + + writer->addArgument( QString("-tsize=%1s").arg(m_isoImager->size()) )->addArgument("-"); + + setWriterJob( writer ); + } + else { + // create cdrdao job + K3bCdrdaoWriter* writer = new K3bCdrdaoWriter( d->doc->burner(), this, this ); + writer->setCommand( K3bCdrdaoWriter::WRITE ); + writer->setSimulate( d->doc->dummy() ); + writer->setBurnSpeed( d->doc->speed() ); + // multisession + writer->setMulti( d->usedMultiSessionMode == K3bDataDoc::START || + d->usedMultiSessionMode == K3bDataDoc::CONTINUE ); + + // now write the tocfile + if( d->tocFile ) delete d->tocFile; + d->tocFile = new KTempFile( QString::null, "toc" ); + d->tocFile->setAutoDelete(true); + + if( QTextStream* s = d->tocFile->textStream() ) { + if( d->usedDataMode == K3b::MODE1 ) { + *s << "CD_ROM" << "\n"; + *s << "\n"; + *s << "TRACK MODE1" << "\n"; + } + else { + *s << "CD_ROM_XA" << "\n"; + *s << "\n"; + *s << "TRACK MODE2_FORM1" << "\n"; + } + + *s << "DATAFILE \"-\" " << m_isoImager->size()*2048 << "\n"; + + d->tocFile->close(); + } + else { + kdDebug() << "(K3bDataJob) could not write tocfile." << endl; + emit infoMessage( i18n("IO Error"), ERROR ); + cancelAll(); + return false; + } + + writer->setTocFile( d->tocFile->name() ); + + setWriterJob( writer ); + } + + return true; +} + + +void K3bDataJob::prepareData() +{ + // we don't need this when only creating image and it is possible + // that the burn device is null + if( d->doc->onlyCreateImages() ) + return; + + // first of all we determine the data mode + if( d->doc->dataMode() == K3b::DATA_MODE_AUTO ) { + if( !d->doc->onlyCreateImages() && + ( d->usedMultiSessionMode == K3bDataDoc::CONTINUE || + d->usedMultiSessionMode == K3bDataDoc::FINISH ) ) { + + // try to get the last track's datamode + // we already asked for an appendable cdr when fetching + // the ms info + kdDebug() << "(K3bDataJob) determining last track's datamode..." << endl; + + // FIXME: use a devicethread + K3bDevice::Toc toc = d->doc->burner()->readToc(); + if( toc.isEmpty() ) { + kdDebug() << "(K3bDataJob) could not retrieve toc." << endl; + emit infoMessage( i18n("Unable to determine the last track's datamode. Using default."), ERROR ); + d->usedDataMode = K3b::MODE2; + } + else { + if( toc[toc.count()-1].mode() == K3bDevice::Track::MODE1 ) + d->usedDataMode = K3b::MODE1; + else + d->usedDataMode = K3b::MODE2; + + kdDebug() << "(K3bDataJob) using datamode: " + << (d->usedDataMode == K3b::MODE1 ? "mode1" : "mode2") + << endl; + } + } + else if( d->usedMultiSessionMode == K3bDataDoc::NONE ) + d->usedDataMode = K3b::MODE1; + else + d->usedDataMode = K3b::MODE2; + } + else + d->usedDataMode = d->doc->dataMode(); + + + // determine the writing mode + if( d->doc->writingMode() == K3b::WRITING_MODE_AUTO ) { + // TODO: put this into the cdreocrdwriter and decide based on the size of the + // track + if( writer()->dao() && d->usedDataMode == K3b::MODE1 && + d->usedMultiSessionMode == K3bDataDoc::NONE ) + d->usedWritingMode = K3b::DAO; + else + d->usedWritingMode = K3b::TAO; + } + else + d->usedWritingMode = d->doc->writingMode(); + + + // cdrecord seems to have problems writing xa 1 disks in dao mode? At least on my system! + if( writingApp() == K3b::DEFAULT ) { + if( d->usedWritingMode == K3b::DAO ) { + if( d->usedMultiSessionMode != K3bDataDoc::NONE ) + d->usedWritingApp = K3b::CDRDAO; + else if( d->usedDataMode == K3b::MODE2 ) + d->usedWritingApp = K3b::CDRDAO; + else + d->usedWritingApp = K3b::CDRECORD; + } + else + d->usedWritingApp = K3b::CDRECORD; + } + else + d->usedWritingApp = writingApp(); +} + + +void K3bDataJob::determineMultiSessionMode() +{ + // + // THIS IS ONLY CALLED IF d->doc->multiSessionMode() == K3bDataDoc::AUTO! + // + + if( d->doc->writingMode() == K3b::WRITING_MODE_AUTO || + d->doc->writingMode() == K3b::TAO ) { + emit newSubTask( i18n("Searching for old session") ); + + // + // Wait for the medium. + // In case an old session was imported we always want to continue or finish a multisession CD/DVD. + // Otherwise we wait for everything we could handle and decide what to do in + // determineMultiSessionMode( K3bDevice::DeviceHandler* ) below. + // + + int wantedMediaState = K3bDevice::STATE_INCOMPLETE|K3bDevice::STATE_EMPTY; + if( d->doc->sessionImported() ) + wantedMediaState = K3bDevice::STATE_INCOMPLETE; + + int m = waitForMedia( d->doc->burner(), + wantedMediaState, + K3bDevice::MEDIA_WRITABLE_CD ); + + if( m < 0 ) + cancel(); + else { + // now we need to determine the media's size + connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::NG_DISKINFO, d->doc->burner() ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotDetermineMultiSessionMode(K3bDevice::DeviceHandler*)) ); + } + } + else { + // we need TAO for multisession + d->usedMultiSessionMode = K3bDataDoc::NONE; + + // carry on with the writing + prepareWriting(); + } +} + + +void K3bDataJob::slotDetermineMultiSessionMode( K3bDevice::DeviceHandler* dh ) +{ + // + // This is a little workaround for the bad cancellation handling in this job + // see cancel() + // + if( d->canceled ) { + if( active() ) { + cleanup(); + jobFinished( false ); + } + } + else { + d->usedMultiSessionMode = getMultiSessionMode( dh->diskInfo() ); + + // carry on with the writing + prepareWriting(); + } +} + + +K3bDataDoc::MultiSessionMode K3bDataJob::getMultiSessionMode( const K3bDevice::DiskInfo& info ) +{ + if( info.appendable() ) { + // + // 3 cases: + // 1. the project does not fit -> no multisession (resulting in asking for another media above) + // 2. the project does fit and fills up the CD -> finish multisession + // 3. the project does fit and does not fill up the CD -> continue multisession + // + // In case a session has been imported we do not consider NONE at all. + // + if( d->doc->size() > info.remainingSize().mode1Bytes() && !d->doc->sessionImported() ) + d->usedMultiSessionMode = K3bDataDoc::NONE; + else if( d->doc->size() >= info.remainingSize().mode1Bytes()*9/10 ) + d->usedMultiSessionMode = K3bDataDoc::FINISH; + else + d->usedMultiSessionMode = K3bDataDoc::CONTINUE; + } + + else if( info.empty() ) { + // + // We only close the CD if the project fills up the CD almost completely (90%) + // + if( d->doc->size() >= info.capacity().mode1Bytes()*9/10 || + d->doc->writingMode() == K3b::DAO ) + d->usedMultiSessionMode = K3bDataDoc::NONE; + else + d->usedMultiSessionMode = K3bDataDoc::START; + } + + else { // complete (WE SHOULD ACTUALLY NEVER GET HERE SINCE WE WAIT FOR AN EMPTY/APPENDABLE CD ABOVE!) + // + // Now we decide only based on the project size. + // let's just use a 680 MB CD as our reference + // + if( d->doc->size()/1024/1024 >= 680*9/10 || + d->doc->writingMode() == K3b::DAO ) + d->usedMultiSessionMode = K3bDataDoc::NONE; + else + d->usedMultiSessionMode = K3bDataDoc::START; + } + + return d->usedMultiSessionMode; +} + + +void K3bDataJob::cancelAll() +{ + d->canceled = true; + + m_isoImager->cancel(); + m_msInfoFetcher->cancel(); + if( m_writerJob ) + m_writerJob->cancel(); + if( d->verificationJob ) + d->verificationJob->cancel(); + + d->pipe.close(); + + cleanup(); +} + + +bool K3bDataJob::waitForMedium() +{ + emit newSubTask( i18n("Waiting for a medium") ); + if( waitForMedia( d->doc->burner(), + d->usedMultiSessionMode == K3bDataDoc::CONTINUE || + d->usedMultiSessionMode == K3bDataDoc::FINISH ? + K3bDevice::STATE_INCOMPLETE : + K3bDevice::STATE_EMPTY, + K3bDevice::MEDIA_WRITABLE_CD ) < 0 ) { + return false; + } + else + return !d->canceled; +} + + +QString K3bDataJob::jobDescription() const +{ + if( d->doc->onlyCreateImages() ) { + return i18n("Creating Data Image File"); + } + else if( d->doc->multiSessionMode() == K3bDataDoc::NONE || + d->doc->multiSessionMode() == K3bDataDoc::AUTO ) { + return i18n("Writing Data CD") + + ( d->doc->isoOptions().volumeID().isEmpty() + ? QString::null + : QString( " (%1)" ).arg(d->doc->isoOptions().volumeID()) ); + } + else { + return i18n("Writing Multisession CD") + + ( d->doc->isoOptions().volumeID().isEmpty() + ? QString::null + : QString( " (%1)" ).arg(d->doc->isoOptions().volumeID()) ); + } +} + + +QString K3bDataJob::jobDetails() const +{ + if( d->doc->copies() > 1 && + !d->doc->dummy() && + !(d->doc->multiSessionMode() == K3bDataDoc::CONTINUE || + d->doc->multiSessionMode() == K3bDataDoc::FINISH) ) + return i18n("ISO9660 Filesystem (Size: %1) - %n copy", + "ISO9660 Filesystem (Size: %1) - %n copies", + d->doc->copies() ) + .arg(KIO::convertSize( d->doc->size() )); + else + return i18n("ISO9660 Filesystem (Size: %1)") + .arg(KIO::convertSize( d->doc->size() )); +} + + +K3bDataDoc::MultiSessionMode K3bDataJob::usedMultiSessionMode() const +{ + return d->usedMultiSessionMode; +} + + +void K3bDataJob::cleanup() +{ + if( !d->doc->onTheFly() && d->doc->removeImages() ) { + if( QFile::exists( d->doc->tempDir() ) ) { + d->imageFile.remove(); + emit infoMessage( i18n("Removed image file %1").arg(d->doc->tempDir()), K3bJob::SUCCESS ); + } + } + + if( d->tocFile ) { + delete d->tocFile; + d->tocFile = 0; + } +} + + +bool K3bDataJob::hasBeenCanceled() const +{ + return d->canceled; +} + +#include "k3bdatajob.moc" diff --git a/libk3b/projects/datacd/k3bdatajob.h b/libk3b/projects/datacd/k3bdatajob.h new file mode 100644 index 0000000..58de969 --- /dev/null +++ b/libk3b/projects/datacd/k3bdatajob.h @@ -0,0 +1,111 @@ +/* + * + * $Id: k3bdatajob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BDATAJOB_H +#define K3BDATAJOB_H + +#include +#include + +#include + +class QString; +class QDataStream; +class K3bAbstractWriter; +class K3bIsoImager; +class KTempFile; +class K3bMsInfoFetcher; + +namespace K3bDevice { + class DeviceHandler; + class DiskInfo; +} + +/** + *@author Sebastian Trueg + */ +class K3bDataJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bDataJob( K3bDataDoc*, K3bJobHandler*, QObject* parent = 0 ); + virtual ~K3bDataJob(); + + K3bDoc* doc() const; + K3bDevice::Device* writer() const; + + virtual bool hasBeenCanceled() const; + + virtual QString jobDescription() const; + virtual QString jobDetails() const; + + public slots: + void cancel(); + void start(); + + /** + * Used to specify a non-default writer. + * If this does notget called K3bDataJob determines + * the writer itself. + */ + void setWriterJob( K3bAbstractWriter* ); + void setImager( K3bIsoImager* ); + + protected slots: + void slotIsoImagerFinished( bool success ); + void slotIsoImagerPercent(int); + void slotWriterJobPercent( int p ); + void slotWriterNextTrack( int t, int tt ); + void slotWriterJobFinished( bool success ); + void slotVerificationProgress( int ); + void slotVerificationFinished( bool ); + void slotMsInfoFetched(bool); + void slotDetermineMultiSessionMode( K3bDevice::DeviceHandler* dh ); + void writeImage(); + void cancelAll(); + + /** + * Just a little helper method that makes subclassing easier. + * Basically used for DVD writing. + */ + virtual bool waitForMedium(); + + protected: + virtual void prepareData(); + virtual bool prepareWriterJob(); + virtual void prepareImager(); + virtual void determineMultiSessionMode(); + virtual K3bDataDoc::MultiSessionMode getMultiSessionMode( const K3bDevice::DiskInfo& ); + virtual void cleanup(); + + K3bDataDoc::MultiSessionMode usedMultiSessionMode() const; + + K3bAbstractWriter* m_writerJob; + K3bIsoImager* m_isoImager; + K3bMsInfoFetcher* m_msInfoFetcher; + + private: + bool startWriterJob(); + bool startOnTheFlyWriting(); + void prepareWriting(); + void connectImager(); + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/datacd/k3bdatapreparationjob.cpp b/libk3b/projects/datacd/k3bdatapreparationjob.cpp new file mode 100644 index 0000000..dd29d6d --- /dev/null +++ b/libk3b/projects/datacd/k3bdatapreparationjob.cpp @@ -0,0 +1,283 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bdatapreparationjob.h" +#include "k3bdatadoc.h" +#include "k3bisooptions.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +class K3bDataPreparationJob::Private : public K3bThread +{ +public: + Private( K3bDataDoc* doc ); + + void run(); + void cancel(); + + K3bDataDoc* doc; + + QValueList nonExistingItems; + QString listOfRenamedItems; + QValueList folderSymLinkItems; + + K3bThreadJob* threadJob; + + bool canceled; +}; + + +K3bDataPreparationJob::Private::Private( K3bDataDoc* _doc ) + : doc(_doc) +{ +} + + +void K3bDataPreparationJob::Private::run() +{ + emitStarted(); + + // clean up + nonExistingItems.clear(); + listOfRenamedItems.truncate(0); + folderSymLinkItems.clear(); + + // initialize filenames in the project + doc->prepareFilenames(); + + // create the message string for the renamed files + if( doc->needToCutFilenames() ) { + int maxlines = 10; + QValueList::const_iterator it; + for( it = doc->needToCutFilenameItems().begin(); + maxlines > 0 && it != doc->needToCutFilenameItems().end(); + ++it, --maxlines ) { + K3bDataItem* item = *it; + listOfRenamedItems += i18n("%1 renamed to %2") + .arg( KStringHandler::csqueeze( item->k3bName(), 30 ) ) + .arg( KStringHandler::csqueeze( item->writtenName(), 30 ) ); + listOfRenamedItems += "
"; + } + if( it != doc->needToCutFilenameItems().end() ) + listOfRenamedItems += "..."; + } + + // + // Check for missing files and folder symlinks + // + K3bDataItem* item = doc->root(); + while( (item = item->nextSibling()) ) { + + if( item->isSymLink() ) { + if( doc->isoOptions().followSymbolicLinks() ) { + QFileInfo f( K3b::resolveLink( item->localPath() ) ); + if( !f.exists() ) { + nonExistingItems.append( item ); + } + else if( f.isDir() ) { + folderSymLinkItems.append( item ); + } + } + } + else if( item->isFile() && !QFile::exists( item->localPath() ) ) { + nonExistingItems.append( item ); + } + + if( canceled ) { + emitCanceled(); + emitFinished(false); + return; + } + } + + + emitFinished( true ); +} + + +void K3bDataPreparationJob::Private::cancel() +{ + canceled = true; +} + + + + +static QString createItemsString( const QValueList& items, unsigned int max ) +{ + QString s; + unsigned int cnt = 0; + for( QValueList::const_iterator it = items.begin(); + it != items.end(); ++it ) { + + s += KStringHandler::csqueeze( (*it)->localPath(), 60 ); + + ++cnt; + if( cnt >= max || it == items.end() ) + break; + + s += "
"; + } + + if( items.count() > max ) + s += "..."; + + return s; +} + + +K3bDataPreparationJob::K3bDataPreparationJob( K3bDataDoc* doc, K3bJobHandler* hdl, QObject* parent ) + : K3bJob( hdl, parent ) +{ + d = new Private( doc ); + d->threadJob = new K3bThreadJob( d, this, this ); + connectSubJob( d->threadJob, SLOT(slotWorkDone(bool)), K3bJob::DEFAULT_SIGNAL_CONNECTION ); +} + + +K3bDataPreparationJob::~K3bDataPreparationJob() +{ + delete d; +} + + +void K3bDataPreparationJob::start() +{ + if( !active() ) { + d->canceled = false; + jobStarted(); + d->threadJob->start(); + } +} + + +void K3bDataPreparationJob::slotWorkDone( bool success ) +{ + if( success ) { + if( !d->listOfRenamedItems.isEmpty() ) { + if( !questionYesNo( "

" + i18n("Some filenames need to be shortened due to the %1 char restriction " + "of the Joliet extensions. If the Joliet extensions are disabled filenames " + "do not have to be shortened but long filenames will not be available on " + "Windows systems.") + .arg( d->doc->isoOptions().jolietLong() ? 103 : 64 ) + + "

" + d->listOfRenamedItems, + i18n("Warning"), + i18n("Shorten Filenames"), + i18n("Disable Joliet extensions") ) ) { + // No -> disable joliet + // for now we enable RockRidge to be sure we did not lie above (keep long filenames) + K3bIsoOptions op = d->doc->isoOptions(); + op.setCreateJoliet( false ); + op.setCreateRockRidge( true ); + d->doc->setIsoOptions( op ); + d->doc->prepareFilenames(); + } + } + + // + // The joliet extension encodes the volume desc in UCS-2, i.e. uses 16 bit for each char. + // Thus, the max length here is 16. + // + if( d->doc->isoOptions().createJoliet() && + d->doc->isoOptions().volumeID().length() > 16 ) { + if( !questionYesNo( "

" + i18n("The Joliet extensions (which are needed for long filenames on Windows systems) " + "restrict the length of the volume descriptior (the name of the filesystem) " + "to %1 characters. The selected descriptor '%2' is longer than that. Do you " + "want it to be cut or do you want to go back and change it manually?") + .arg( 16 ).arg( d->doc->isoOptions().volumeID() ), + i18n("Warning"), + i18n("Cut volume descriptor in the Joliet tree"), + i18n("Cancel and go back") ) ) { + d->canceled = true; + emit canceled(); + jobFinished( false ); + return; + } + } + + // + // Check for missing files + // + if( !d->nonExistingItems.isEmpty() ) { + if( questionYesNo( "

" + i18n("The following files could not be found. Do you want to remove them from the " + "project and continue without adding them to the image?") + + "

" + createItemsString( d->nonExistingItems, 10 ), + i18n("Warning"), + i18n("Remove missing files and continue"), + i18n("Cancel and go back") ) ) { + for( QValueList::const_iterator it = d->nonExistingItems.begin(); + it != d->nonExistingItems.end(); ++it ) { + delete *it; + } + } + else { + d->canceled = true; + emit canceled(); + jobFinished(false); + return; + } + } + + // + // Warn about symlinks to folders + // + if( d->doc->isoOptions().followSymbolicLinks() && !d->folderSymLinkItems.isEmpty() ) { + if( !questionYesNo( "

" + i18n("K3b is not able to follow symbolic links to folders after they have been added " + "to the project. Do you want to continue " + "without writing the symbolic links to the image?") + + "

" + createItemsString( d->folderSymLinkItems, 10 ), + i18n("Warning"), + i18n("Discard symbolic links to folders"), + i18n("Cancel and go back") ) ) { + d->canceled = true; + emit canceled(); + jobFinished(false); + return; + } + } + + jobFinished( true ); + } + else { + if( d->canceled ) + emit canceled(); + jobFinished(false); + } +} + + +void K3bDataPreparationJob::cancel() +{ + d->cancel(); +} + + +bool K3bDataPreparationJob::hasBeenCanceled() const +{ + return d->canceled; +} + +#include "k3bdatapreparationjob.moc" diff --git a/libk3b/projects/datacd/k3bdatapreparationjob.h b/libk3b/projects/datacd/k3bdatapreparationjob.h new file mode 100644 index 0000000..1c83a42 --- /dev/null +++ b/libk3b/projects/datacd/k3bdatapreparationjob.h @@ -0,0 +1,51 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_DATA_PREPARATION_JOB_H_ +#define _K3B_DATA_PREPARATION_JOB_H_ + +#include + + +class K3bDataDoc; +class K3bJobHandler; + +/** + * The K3bDataPreparationJob performs some checks on the data in a data project + * It is used by th K3bIsoImager. + */ +class K3bDataPreparationJob : public K3bJob +{ + Q_OBJECT + + public: + K3bDataPreparationJob( K3bDataDoc* doc, K3bJobHandler* hdl, QObject* parent ); + ~K3bDataPreparationJob(); + + bool hasBeenCanceled() const; + + public slots: + void start(); + void cancel(); + + private slots: + void slotWorkDone( bool success ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/datacd/k3bdiritem.cpp b/libk3b/projects/datacd/k3bdiritem.cpp new file mode 100644 index 0000000..3ea3236 --- /dev/null +++ b/libk3b/projects/datacd/k3bdiritem.cpp @@ -0,0 +1,406 @@ +/* + * + * $Id: k3bdiritem.cpp 652578 2007-04-11 14:21:04Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bdiritem.h" +#include "k3bdatadoc.h" +#include "k3bsessionimportitem.h" +#include "k3bfileitem.h" + +#include +#include + +#include + + +K3bDirItem::K3bDirItem(const QString& name, K3bDataDoc* doc, K3bDirItem* parentDir) + : K3bDataItem( doc, parentDir ), + m_size(0), + m_followSymlinksSize(0), + m_blocks(0), + m_followSymlinksBlocks(0), + m_files(0), + m_dirs(0) +{ + m_k3bName = name; + + // add automagically like a qlistviewitem + if( parent() ) + parent()->addDataItem( this ); +} + + +K3bDirItem::K3bDirItem( const K3bDirItem& item ) + : K3bDataItem( item ), + m_size(0), + m_followSymlinksSize(0), + m_blocks(0), + m_followSymlinksBlocks(0), + m_files(0), + m_dirs(0), + m_localPath( item.m_localPath ) +{ + for( QPtrListIterator it( item.children() ); *it; ++it ) + addDataItem( (*it)->copy() ); +} + +K3bDirItem::~K3bDirItem() +{ + // delete all children + // doing this by hand is much saver than using the + // auto-delete feature since some of the items' destructors + // may change the list + K3bDataItem* i = m_children.first(); + while( i ) { + // it is important to use takeDataItem here to be sure + // the size gets updated properly + takeDataItem(i); + delete i; + i = m_children.first(); + } + + // this has to be done after deleting the children + // because the directory itself has a size of 0 in K3b + // and all it's files' sizes have already been substracted + take(); +} + + +K3bDataItem* K3bDirItem::copy() const +{ + return new K3bDirItem( *this ); +} + + +K3bDirItem* K3bDirItem::getDirItem() const +{ + return const_cast(this); +} + +K3bDirItem* K3bDirItem::addDataItem( K3bDataItem* item ) +{ + // check if we are a subdir of item + if( K3bDirItem* dirItem = dynamic_cast(item) ) { + if( dirItem->isSubItem( this ) ) { + kdDebug() << "(K3bDirItem) trying to move a dir item down in it's own tree." << endl; + return this; + } + } + + if( m_children.findRef( item ) == -1 ) { + if( item->isFile() ) { + // do we replace an old item? + QString name = item->k3bName(); + int cnt = 1; + while( K3bDataItem* oldItem = find( name ) ) { + if( !oldItem->isDir() && oldItem->isFromOldSession() ) { + // in this case we remove this item from it's parent and save it in the new one + // to be able to recover it + oldItem->take(); + static_cast(oldItem)->setReplaceItem( static_cast(item) ); + static_cast(item)->setReplacedItemFromOldSession( oldItem ); + break; + } + else { + // + // add a counter to the filename + // + if( item->k3bName()[item->k3bName().length()-4] == '.' ) + name = item->k3bName().left( item->k3bName().length()-4 ) + QString::number(cnt++) + item->k3bName().right(4); + else + name = item->k3bName() + QString::number(cnt++); + } + } + item->setK3bName( name ); + } + + m_children.append( item->take() ); + updateSize( item, false ); + if( item->isDir() ) + updateFiles( ((K3bDirItem*)item)->numFiles(), ((K3bDirItem*)item)->numDirs()+1 ); + else + updateFiles( 1, 0 ); + + item->m_parentDir = this; + + // inform the doc + if( doc() ) + doc()->itemAddedToDir( this, item ); + } + + return this; +} + + +K3bDataItem* K3bDirItem::takeDataItem( K3bDataItem* item ) +{ + int x = m_children.findRef( item ); + if( x > -1 ) { + K3bDataItem* item = m_children.take(); + updateSize( item, true ); + if( item->isDir() ) + updateFiles( -1*((K3bDirItem*)item)->numFiles(), -1*((K3bDirItem*)item)->numDirs()-1 ); + else + updateFiles( -1, 0 ); + + item->m_parentDir = 0; + + // inform the doc + if( doc() ) + doc()->itemRemovedFromDir( this, item ); + + if( item->isFile() ) { + // restore the item imported from an old session + if( static_cast(item)->replaceItemFromOldSession() ) + addDataItem( static_cast(item)->replaceItemFromOldSession() ); + } + + return item; + } + else + return 0; +} + + +K3bDataItem* K3bDirItem::nextSibling() const +{ + if( !m_children.isEmpty() ) + return m_children.getFirst(); + else + return K3bDataItem::nextSibling(); +} + + +K3bDataItem* K3bDirItem::nextChild( K3bDataItem* prev ) const +{ + // search for prev in children + if( m_children.findRef( prev ) < 0 ) { + return 0; + } + else + return m_children.next(); +} + + +bool K3bDirItem::alreadyInDirectory( const QString& filename ) const +{ + return (find( filename ) != 0); +} + + +K3bDataItem* K3bDirItem::find( const QString& filename ) const +{ + for( QPtrListIterator it( m_children ); it.current(); ++it ) { + if( it.current()->k3bName() == filename ) + return it.current(); + } + return 0; +} + + +K3bDataItem* K3bDirItem::findByPath( const QString& p ) +{ + if( p.isEmpty() || p == "/" ) + return this; + + QString path = p; + if( path.startsWith("/") ) + path = path.mid(1); + int pos = path.find( "/" ); + if( pos < 0 ) + return find( path ); + else { + // do it recursivly + K3bDataItem* item = find( path.left(pos) ); + if( item && item->isDir() ) + return ((K3bDirItem*)item)->findByPath( path.mid( pos+1 ) ); + else + return 0; + } +} + + +bool K3bDirItem::mkdir( const QString& dirPath ) +{ + // + // An absolut path always starts at the root item + // + if( dirPath[0] == '/' ) { + if( parent() ) + return parent()->mkdir( dirPath ); + else + return mkdir( dirPath.mid( 1 ) ); + } + + if( findByPath( dirPath ) ) + return false; + + QString restPath; + QString dirName; + int pos = dirPath.find( '/' ); + if( pos == -1 ) { + dirName = dirPath; + } + else { + dirName = dirPath.left( pos ); + restPath = dirPath.mid( pos+1 ); + } + + K3bDataItem* dir = find( dirName ); + if( !dir ) + dir = new K3bDirItem( dirName, doc(), this ); + else if( !dir->isDir() ) + return false; + + if( !restPath.isEmpty() ) + return static_cast(dir)->mkdir( restPath ); + + return true; +} + + +KIO::filesize_t K3bDirItem::itemSize( bool followsylinks ) const +{ + if( followsylinks ) + return m_followSymlinksSize; + else + return m_size; +} + + +K3b::Msf K3bDirItem::itemBlocks( bool followSymlinks ) const +{ + if( followSymlinks ) + return m_followSymlinksBlocks; + else + return m_blocks; +} + + +bool K3bDirItem::isSubItem( K3bDataItem* item ) const +{ + if( dynamic_cast(item) == this ) + return true; + + K3bDirItem* d = item->parent(); + while( d ) { + if( d == this ) { + return true; + } + d = d->parent(); + } + + return false; +} + + +long K3bDirItem::numFiles() const +{ + return m_files; +} + + +long K3bDirItem::numDirs() const +{ + return m_dirs; +} + + +bool K3bDirItem::isRemoveable() const +{ + if( !K3bDataItem::isRemoveable() ) + return false; + + for( QPtrListIterator it( m_children ); it.current(); ++it ) { + if( !it.current()->isRemoveable() ) + return false; + } + + return true; +} + + +void K3bDirItem::updateSize( K3bDataItem* item, bool removed ) +{ + if ( !item->isFromOldSession() ) { + if( removed ) { + m_followSymlinksSize -= item->itemSize( true ); + m_size -= item->itemSize( false ); + m_followSymlinksBlocks -= item->itemBlocks( true ).lba(); + m_blocks -= item->itemBlocks( false ).lba(); + } + else { + m_followSymlinksSize += item->itemSize( true ); + m_size += item->itemSize( false ); + m_followSymlinksBlocks += item->itemBlocks( true ).lba(); + m_blocks += item->itemBlocks( false ).lba(); + } + } + + if( parent() ) + parent()->updateSize( item, removed ); +} + +void K3bDirItem::updateFiles( long files, long dirs ) +{ + m_files += files; + m_dirs += dirs; + if( parent() ) + parent()->updateFiles( files, dirs ); +} + + +bool K3bDirItem::isFromOldSession() const +{ + for( QPtrListIterator it( m_children ); it.current(); ++it ) { + if( (*it)->isFromOldSession() ) + return true; + } + return false; +} + + +bool K3bDirItem::writeToCd() const +{ + // check if this dir contains items to write + for( QPtrListIterator it( m_children ); it.current(); ++it ) { + if( (*it)->writeToCd() ) + return true; + } + return K3bDataItem::writeToCd(); +} + + +K3bRootItem::K3bRootItem( K3bDataDoc* doc ) + : K3bDirItem( "root", doc, 0 ) +{ +} + + +K3bRootItem::~K3bRootItem() +{ +} + + +const QString& K3bRootItem::k3bName() const +{ + return doc()->isoOptions().volumeID(); +} + + +void K3bRootItem::setK3bName( const QString& text ) +{ + doc()->setVolumeID( text ); +} diff --git a/libk3b/projects/datacd/k3bdiritem.h b/libk3b/projects/datacd/k3bdiritem.h new file mode 100644 index 0000000..a64b4fd --- /dev/null +++ b/libk3b/projects/datacd/k3bdiritem.h @@ -0,0 +1,155 @@ +/* + * + * $Id: k3bdiritem.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BDIRITEM_H +#define K3BDIRITEM_H + + +#include +#include + +#include + +#include "k3bdataitem.h" +#include "k3b_export.h" +class K3bDataDoc; + +/** + *@author Sebastian Trueg + */ + +class LIBK3B_EXPORT K3bDirItem : public K3bDataItem +{ + public: + K3bDirItem( const QString& name, K3bDataDoc*, K3bDirItem* parentDir = 0 ); + + /** + * Default copy constructor. Copies the dir including all children. However, none of the + * children will have set a doc and the copy dir will not have set a parent dir. + */ + K3bDirItem( const K3bDirItem& ); + + virtual ~K3bDirItem(); + + K3bDataItem* copy() const; + + K3bDirItem* getDirItem() const; + + const QPtrList& children() const { return m_children; } + K3bDirItem* addDataItem( K3bDataItem* item ); + K3bDataItem* takeDataItem( K3bDataItem* item ); + + K3bDataItem* nextSibling() const; + K3bDataItem* nextChild( K3bDataItem* ) const; + + bool alreadyInDirectory( const QString& fileName ) const; + K3bDataItem* find( const QString& filename ) const; + K3bDataItem* findByPath( const QString& ); + + long numFiles() const; + long numDirs() const; + + bool isEmpty() const { return ( numDirs() + numFiles() == 0 ); } + + /** + * returns true if item is a subItem of + * this dir item + * (returns also true if item == this + */ + bool isSubItem( K3bDataItem* item ) const; + + bool isDir() const { return true; } + + virtual bool isRemoveable() const; + + /** + * \return true if some child is from an old session. + */ + virtual bool isFromOldSession() const; + + /** + * Recursively creates a directory. + */ + bool mkdir( const QString& dir ); + + void setLocalPath( const QString& p ) { m_localPath = p; } + QString localPath() const { return m_localPath; } + + /** + * \reimplemented + */ + bool writeToCd() const; + + protected: + /** + * Normally one does not use this method but K3bDataItem::size() + * + * This method does not take into account the possibility to share the data + * between files with the same inode in an iso9660 filesystem. + * For that one has to use K3bFileCompilationSizeHandler. + */ + KIO::filesize_t itemSize( bool followSymlinks ) const; + + /* + * Normally one does not use this method but K3bDataItem::blocks() + */ + K3b::Msf itemBlocks( bool followSymlinks ) const; + + private: + /** + * this recursivly updates the size of the directories. + * The size of this dir and the parent dir is updated. + * These values are just used for user information. + */ + void updateSize( K3bDataItem*, bool removed = false ); + /** + * Updates the number of files and directories. These values are + * just used for user information. + */ + void updateFiles( long files, long dirs ); + + mutable QPtrList m_children; + + // size of the items simply added + KIO::filesize_t m_size; + KIO::filesize_t m_followSymlinksSize; + + // number of blocks (2048 bytes) used by all the items + long m_blocks; + long m_followSymlinksBlocks; + + long m_files; + long m_dirs; + + // HACK: store the original path to be able to use it's permissions + // ´remove this once we have a backup project + QString m_localPath; +}; + + +class K3bRootItem : public K3bDirItem +{ + public: + K3bRootItem( K3bDataDoc* ); + ~K3bRootItem(); + + const QString& k3bName() const; + void setK3bName( const QString& ); + + bool isMoveable() const { return false; } + bool isRemoveable() const { return false; } +}; +#endif diff --git a/libk3b/projects/datacd/k3bfilecompilationsizehandler.cpp b/libk3b/projects/datacd/k3bfilecompilationsizehandler.cpp new file mode 100644 index 0000000..0ddab76 --- /dev/null +++ b/libk3b/projects/datacd/k3bfilecompilationsizehandler.cpp @@ -0,0 +1,228 @@ +/* + * + * $Id: k3bfilecompilationsizehandler.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bfilecompilationsizehandler.h" +#include "k3bfileitem.h" + +#include + +#include +#include +#include + + +// TODO: remove the items from the project if the savedSize differs +// with some info-widget: "Files xxx have changed on disk. Removing them from the project." +// or we just update the sizes! + + +static long usedBlocks( const KIO::filesize_t& bytes ) +{ + if( bytes % 2048 ) + return bytes/2048 + 1; + else + return bytes/2048; +} + + +class InodeInfo +{ +public: + InodeInfo() { + number = 0; + savedSize = 0; + } + + /** + * How often has the file with + * the corresponding inode been added + */ + int number; + + /** + * The size of the first added file. This has to be saved + * to check further addings and to avoid the following situation: + * A file with inode 1 is added, then deleted. Another file is created + * at inode 1 and added to the project. Now the first file gets + * removed and then the second. If we had not saved the size we would + * have added the size of the first and removed the size of the second + * file resulting in a corrupted project size. + * This way we always use the size of the first added file and may + * warn the user if sizes differ. + */ + KIO::filesize_t savedSize; + + KIO::filesize_t completeSize() const { return savedSize*number; } + + /** + * In an iso9660 filesystem a file occupies complete blocks of 2048 bytes. + */ + K3b::Msf blocks() const { return K3b::Msf( usedBlocks(savedSize) ); } + + QPtrList items; +}; + + +class K3bFileCompilationSizeHandler::Private +{ +public: + Private() + : size(0) { + } + + void clear() { + inodeMap.clear(); + size = 0; + blocks = 0; + } + + void addFile( K3bFileItem* item, bool followSymlinks ) { + InodeInfo& inodeInfo = inodeMap[item->localId(followSymlinks)]; + + inodeInfo.items.append( item ); + + if( inodeInfo.number == 0 ) { + inodeInfo.savedSize = item->itemSize( followSymlinks ); + + size += inodeInfo.savedSize; + blocks += inodeInfo.blocks(); + } + + inodeInfo.number++; + } + + void addSpecialItem( K3bDataItem* item ) { + // special files do not have a corresponding local file + // so we just add their k3bSize + size += item->size(); + blocks += usedBlocks(item->size()); + specialItems.append( item ); + } + + void removeFile( K3bFileItem* item, bool followSymlinks ) { + InodeInfo& inodeInfo = inodeMap[item->localId(followSymlinks)]; + + if( inodeInfo.items.findRef( item ) == -1 ) { + kdError() << "(K3bFileCompilationSizeHandler) " + << item->localPath() + << " has been removed without being added!" << endl; + } + else { + if( item->itemSize(followSymlinks) != inodeInfo.savedSize ) { + kdError() << "(K3bFileCompilationSizeHandler) savedSize differs!" << endl; + } + + inodeInfo.items.removeRef( item ); + inodeInfo.number--; + if( inodeInfo.number == 0 ) { + size -= inodeInfo.savedSize; + blocks -= inodeInfo.blocks(); + } + } + } + + void removeSpecialItem( K3bDataItem* item ) { + // special files do not have a corresponding local file + // so we just substract their k3bSize + if( specialItems.findRef( item ) == -1 ) { + kdError() << "(K3bFileCompilationSizeHandler) Special item " + << item->k3bName() + << " has been removed without being added!" << endl; + } + else { + specialItems.removeRef( item ); + size -= item->size(); + blocks -= usedBlocks(item->size()); + } + } + + + /** + * This maps from inodes to the number of occurrences of the inode. + */ + QMap inodeMap; + + KIO::filesize_t size; + K3b::Msf blocks; + + QPtrList specialItems; +}; + + + +K3bFileCompilationSizeHandler::K3bFileCompilationSizeHandler() +{ + d_symlinks = new Private; + d_noSymlinks = new Private; +} + +K3bFileCompilationSizeHandler::~K3bFileCompilationSizeHandler() +{ + delete d_symlinks; + delete d_noSymlinks; +} + + +const KIO::filesize_t& K3bFileCompilationSizeHandler::size( bool followSymlinks ) const +{ + if( followSymlinks ) + return d_noSymlinks->size; + else + return d_symlinks->size; +} + + +const K3b::Msf& K3bFileCompilationSizeHandler::blocks( bool followSymlinks ) const +{ + if( followSymlinks ) + return d_noSymlinks->blocks; + else + return d_symlinks->blocks; +} + + +void K3bFileCompilationSizeHandler::addFile( K3bDataItem* item ) +{ + if( item->isSpecialFile() ) { + d_symlinks->addSpecialItem( item ); + d_noSymlinks->addSpecialItem( item ); + } + else if( item->isFile() ) { + K3bFileItem* fileItem = static_cast( item ); + d_symlinks->addFile( fileItem, false ); + d_noSymlinks->addFile( fileItem, true ); + } +} + + +void K3bFileCompilationSizeHandler::removeFile( K3bDataItem* item ) +{ + if( item->isSpecialFile() ) { + d_symlinks->removeSpecialItem( item ); + d_noSymlinks->removeSpecialItem( item ); + } + else if( item->isFile() ) { + K3bFileItem* fileItem = static_cast( item ); + d_symlinks->removeFile( fileItem, false ); + d_noSymlinks->removeFile( fileItem, true ); + } +} + + +void K3bFileCompilationSizeHandler::clear() +{ + d_symlinks->clear(); + d_noSymlinks->clear(); +} diff --git a/libk3b/projects/datacd/k3bfilecompilationsizehandler.h b/libk3b/projects/datacd/k3bfilecompilationsizehandler.h new file mode 100644 index 0000000..c996657 --- /dev/null +++ b/libk3b/projects/datacd/k3bfilecompilationsizehandler.h @@ -0,0 +1,73 @@ +/* + * + * $Id: k3bfilecompilationsizehandler.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_FILECOMPILATION_SIZE_HANDLER_H_ +#define _K3B_FILECOMPILATION_SIZE_HANDLER_H_ + + +#include +#include + +class K3bDataItem; + + +/** + * This class maintains a map of indoes and the number + * of files in the doc that belong to that inode. + * This way a more accurate size calculation is possible + * + * It has to be noted that the sizes of the directories + * are only locally true. That means that in some cases + * the root directory of the project may show a much + * higher size than calculated by this class. + */ +class K3bFileCompilationSizeHandler +{ + public: + K3bFileCompilationSizeHandler(); + ~K3bFileCompilationSizeHandler(); + + /** + * This does NOT equal blocks() * 2048. + * This is the sum of the actual file sizes. + */ + const KIO::filesize_t& size( bool followSymlinks = false ) const; + + /** + * Number of blocks the files will occupy. + */ + const K3b::Msf& blocks( bool followSymlinks = false ) const; + + /** + * This will increase the counter for the inode of + * the file in url and update the totel size. + */ + void addFile( K3bDataItem* ); + + /** + * This will decrease the counter for the inode of + * the file in url and update the totel size. + */ + void removeFile( K3bDataItem* ); + + void clear(); + + private: + class Private; + Private* d_symlinks; + Private* d_noSymlinks; +}; + +#endif diff --git a/libk3b/projects/datacd/k3bfileitem.cpp b/libk3b/projects/datacd/k3bfileitem.cpp new file mode 100644 index 0000000..d9e288f --- /dev/null +++ b/libk3b/projects/datacd/k3bfileitem.cpp @@ -0,0 +1,300 @@ +/* + * + * $Id: k3bfileitem.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include +#include + +#include "k3bfileitem.h" +#include "k3bdatadoc.h" +#include "k3bdiritem.h" +#include "k3bisooptions.h" +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +bool operator==( const K3bFileItem::Id& id1, const K3bFileItem::Id& id2 ) +{ + return ( id1.device == id2.device && id1.inode == id2.inode ); +} + + +bool operator<( const K3bFileItem::Id& id1, const K3bFileItem::Id& id2 ) +{ + if( id1.device == id2.device ) + return ( id1.inode < id2.inode ); + else + return ( id1.device < id2.device ); +} + + +bool operator>( const K3bFileItem::Id& id1, const K3bFileItem::Id& id2 ) +{ + return !( id2 < id1 || id1 == id2 ); +} + + + +K3bFileItem::K3bFileItem( const QString& filePath, K3bDataDoc* doc, K3bDirItem* dir, const QString& k3bName, int flags ) + : K3bDataItem( doc, dir, flags ), + m_replacedItemFromOldSession(0), + m_localPath(filePath) +{ + if( k3bName.isEmpty() ) + m_k3bName = filePath.section( '/', -1 ); + else + m_k3bName = k3bName; + + // we determine the size here to avoid problems with removed or renamed files + // we need to use lstat here since for symlinks both KDE and QT return the size of the file pointed to + // instead the size of the link. + k3b_struct_stat statBuf; + if( k3b_lstat( QFile::encodeName(filePath), &statBuf ) ) { + m_size = K3b::filesize( filePath ); + m_id.inode = 0; + m_id.device = 0; + m_bSymLink = false; + + kdError() << "(KFileItem) lstat failed: " << strerror(errno) << endl; + + // since we have no proper inode info, disable the inode caching in the doc + if( doc ) { + K3bIsoOptions o( doc->isoOptions() ); + o.setDoNotCacheInodes( true ); + doc->setIsoOptions( o ); + } + } + else { + m_size = (KIO::filesize_t)statBuf.st_size; + + m_bSymLink = S_ISLNK(statBuf.st_mode); + + // + // integrate the device number into the inode since files on different + // devices may have the same inode number! + // + m_id.inode = statBuf.st_ino; + m_id.device = statBuf.st_dev; + } + + m_idFollowed = m_id; + m_sizeFollowed = m_size; + + if( isSymLink() ) { + k3b_struct_stat statBuf; + if( k3b_stat( QFile::encodeName(filePath), &statBuf ) == 0 ) { + m_idFollowed.inode = statBuf.st_ino; + m_idFollowed.device = statBuf.st_dev; + + m_sizeFollowed = (KIO::filesize_t)statBuf.st_size; + } + } + + // add automagically like a qlistviewitem + if( parent() ) + parent()->addDataItem( this ); +} + + +K3bFileItem::K3bFileItem( const k3b_struct_stat* stat, + const k3b_struct_stat* followedStat, + const QString& filePath, K3bDataDoc* doc, K3bDirItem* dir, const QString& k3bName ) + : K3bDataItem( doc, dir ), + m_replacedItemFromOldSession(0), + m_localPath(filePath) +{ + if( k3bName.isEmpty() ) + m_k3bName = filePath.section( '/', -1 ); + else + m_k3bName = k3bName; + + m_size = (KIO::filesize_t)stat->st_size; + m_bSymLink = S_ISLNK(stat->st_mode); + + // + // integrate the device number into the inode since files on different + // devices may have the same inode number! + // + m_id.inode = stat->st_ino; + m_id.device = stat->st_dev; + + if( isSymLink() ) { + m_idFollowed.inode = followedStat->st_ino; + m_idFollowed.device = followedStat->st_dev; + + m_sizeFollowed = (KIO::filesize_t)followedStat->st_size; + } + else { + m_idFollowed = m_id; + m_sizeFollowed = m_size; + } + + if( parent() ) + parent()->addDataItem( this ); +} + + +K3bFileItem::K3bFileItem( const K3bFileItem& item ) + : K3bDataItem( item ), + m_replacedItemFromOldSession(0), + m_size( item.m_size ), + m_sizeFollowed( item.m_sizeFollowed ), + m_id( item.m_id ), + m_idFollowed( item.m_idFollowed ), + m_localPath( item.m_localPath ), + m_bSymLink( item.m_bSymLink ) +{ +} + + +K3bFileItem::~K3bFileItem() +{ + // remove this from parentdir + take(); +} + + +K3bDataItem* K3bFileItem::copy() const +{ + return new K3bFileItem( *this ); +} + + +KIO::filesize_t K3bFileItem::itemSize( bool followSymlinks ) const +{ + if( followSymlinks ) + return m_sizeFollowed; + else + return m_size; +} + + +K3bFileItem::Id K3bFileItem::localId() const +{ + return localId( doc() ? doc()->isoOptions().followSymbolicLinks() || !doc()->isoOptions().createRockRidge() : false ); +} + + +K3bFileItem::Id K3bFileItem::localId( bool followSymlinks ) const +{ + if( followSymlinks ) + return m_idFollowed; + else + return m_id; +} + + +bool K3bFileItem::exists() const +{ + return true; +} + +QString K3bFileItem::absIsoPath() +{ + // return m_dir->absIsoPath() + m_isoName; + return QString::null; +} + + +QString K3bFileItem::localPath() const +{ + return m_localPath; +} + +K3bDirItem* K3bFileItem::getDirItem() const +{ + return getParent(); +} + + +bool K3bFileItem::isSymLink() const +{ + return m_bSymLink; +} + + +QString K3bFileItem::linkDest() const +{ + return QFileInfo( localPath() ).readLink(); +} + + +bool K3bFileItem::isValid() const +{ + if( isSymLink() ) { + + // this link is not valid if we cannot follow it if we want to + if( doc()->isoOptions().followSymbolicLinks() ) { + return QFile::exists( K3b::resolveLink( localPath() ) ); + } + + QString dest = linkDest(); + + if( dest[0] == '/' ) + return false; // absolut links can never be part of the compilation! + + // parse the link + K3bDirItem* dir = getParent(); + + QStringList tokens = QStringList::split( QRegExp("/+"), dest ); // two slashes or more do the same as one does! + + unsigned int i = 0; + while( i < tokens.size() ) { + if( tokens[i] == "." ) { + // ignore it + } + else if( tokens[i] == ".." ) { + // change the directory + dir = dir->parent(); + if( dir == 0 ) + return false; + } + else { + // search for the item in dir + K3bDataItem* d = dir->find( tokens[i] ); + if( d == 0 ) + return false; + + if( d->isDir() ) { + // change directory + dir = (K3bDirItem*)d; + } + else { + if( i+1 != tokens.size() ) + return false; // if di is a file we need to be at the last token + else + return (dest[dest.length()-1] != '/'); // if the link destination ends with a slash + // it can only point to a directory! + } + } + + i++; + } + + return true; + } + else + return true; +} diff --git a/libk3b/projects/datacd/k3bfileitem.h b/libk3b/projects/datacd/k3bfileitem.h new file mode 100644 index 0000000..f23644f --- /dev/null +++ b/libk3b/projects/datacd/k3bfileitem.h @@ -0,0 +1,124 @@ +/* + * + * $Id: k3bfileitem.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BFILEITEM_H +#define K3BFILEITEM_H + + +#include "k3bdataitem.h" +#include + +#include +#include + +#include "k3b_export.h" + +class K3bDataDoc; +class K3bDirItem; + + +/** + *@author Sebastian Trueg + */ +class LIBK3B_EXPORT K3bFileItem : public K3bDataItem +{ +public: + /** + * Creates a new K3bFileItem + */ + K3bFileItem( const QString& fileName, K3bDataDoc* doc, K3bDirItem* dir, const QString& k3bName = 0, int flags = 0 ); + + /** + * Constructor for optimized file item creation which does no additional stat. + * + * Used by K3b to speedup file item creation. + */ + K3bFileItem( const k3b_struct_stat* stat, + const k3b_struct_stat* followedStat, + const QString& fileName, K3bDataDoc* doc, K3bDirItem* dir, const QString& k3bName = 0 ); + + /** + * Default copy constructor + * Creates a copy of the fileitem. The copy, however, is not an exact duplicate of this item. + * The copy does not have a parent dir set and any old session items are set to 0. + */ + K3bFileItem( const K3bFileItem& ); + + virtual ~K3bFileItem(); + + virtual K3bDataItem* copy() const; + + bool exists() const; + + QString absIsoPath(); + + /** reimplemented from K3bDataItem */ + QString localPath() const; + + /** + * Identification of the files on the local device. + */ + struct Id { + dev_t device; + ino_t inode; + }; + + /** + * This is not the normal inode number but it also contains + * the device number. + */ + Id localId() const; + + /** + * The id of the file the symlink is pointing to + */ + Id localId( bool followSymlinks ) const; + + K3bDirItem* getDirItem() const; + + bool isSymLink() const; + QString linkDest() const; + bool isFile() const { return true; } + + /** returns true if the item is not a link or + * if the link's destination is part of the compilation */ + bool isValid() const; + + K3bDataItem* replaceItemFromOldSession() const { return m_replacedItemFromOldSession; } + void setReplacedItemFromOldSession( K3bDataItem* item ) { m_replacedItemFromOldSession = item; } + + /** + * Normally one does not use this method but K3bDataItem::size() + */ + KIO::filesize_t itemSize( bool followSymlinks ) const; + + private: + K3bDataItem* m_replacedItemFromOldSession; + + KIO::filesize_t m_size; + KIO::filesize_t m_sizeFollowed; + Id m_id; + Id m_idFollowed; + + QString m_localPath; + bool m_bSymLink; +}; + +bool operator==( const K3bFileItem::Id&, const K3bFileItem::Id& ); +bool operator<( const K3bFileItem::Id&, const K3bFileItem::Id& ); +bool operator>( const K3bFileItem::Id&, const K3bFileItem::Id& ); + +#endif diff --git a/libk3b/projects/datacd/k3bisoimager.cpp b/libk3b/projects/datacd/k3bisoimager.cpp new file mode 100644 index 0000000..f44d3ab --- /dev/null +++ b/libk3b/projects/datacd/k3bisoimager.cpp @@ -0,0 +1,1187 @@ +/* + * + * $Id: k3bisoimager.cpp 655085 2007-04-17 17:48:36Z trueg $ + * Copyright (C) 2003-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include +#include + +#include "k3bisoimager.h" +#include "k3bdiritem.h" +#include "k3bbootitem.h" +#include "k3bdatadoc.h" +#include "k3bdatapreparationjob.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +int K3bIsoImager::s_imagerSessionCounter = 0; + + +class K3bIsoImager::Private +{ +public: + Private() + : pipe(0) { + } + + ~Private() { + delete pipe; + } + + QString imagePath; + K3bFileSplitter imageFile; + const K3bExternalBin* mkisofsBin; + + enum LinkHandling { + KEEP_ALL, + FOLLOW, + DISCARD_ALL, + DISCARD_BROKEN + }; + + int usedLinkHandling; + + bool knownError; + + K3bActivePipe* pipe; + K3bDataPreparationJob* dataPreparationJob; +}; + + +K3bIsoImager::K3bIsoImager( K3bDataDoc* doc, K3bJobHandler* hdl, QObject* parent, const char* name ) + : K3bJob( hdl, parent, name ), + m_pathSpecFile(0), + m_rrHideFile(0), + m_jolietHideFile(0), + m_sortWeightFile(0), + m_process( 0 ), + m_processExited(false), + m_doc( doc ), + m_noDeepDirectoryRelocation( false ), + m_importSession( false ), + m_device(0), + m_mkisofsPrintSizeResult( 0 ), + m_fdToWriteTo(-1) +{ + d = new Private(); + d->dataPreparationJob = new K3bDataPreparationJob( doc, this, this ); + connectSubJob( d->dataPreparationJob, + SLOT(slotDataPreparationDone(bool)), + DEFAULT_SIGNAL_CONNECTION ); +} + + +K3bIsoImager::~K3bIsoImager() +{ + cleanup(); + delete d; +} + + +bool K3bIsoImager::active() const +{ + return K3bJob::active(); +} + + +void K3bIsoImager::writeToFd( int fd ) +{ + m_fdToWriteTo = fd; +} + + +void K3bIsoImager::writeToImageFile( const QString& path ) +{ + d->imagePath = path; + m_fdToWriteTo = -1; +} + + +void K3bIsoImager::slotReceivedStderr( const QString& line ) +{ + parseMkisofsOutput( line ); + emit debuggingOutput( "mkisofs", line ); +} + + +void K3bIsoImager::handleMkisofsProgress( int p ) +{ + emit percent( p ); +} + + +void K3bIsoImager::handleMkisofsInfoMessage( const QString& line, int type ) +{ + emit infoMessage( line, type ); + if( type == ERROR ) + d->knownError = true; +} + + +void K3bIsoImager::slotProcessExited( KProcess* p ) +{ + kdDebug() << k_funcinfo << endl; + + m_processExited = true; + + d->pipe->close(); + + emit debuggingOutput( "K3bIsoImager", + QString("Pipe throughput: %1 bytes read, %2 bytes written.") + .arg(d->pipe->bytesRead()).arg(d->pipe->bytesWritten()) ); + + if( d->imageFile.isOpen() ) { + d->imageFile.close(); + + if( m_canceled || p->exitStatus() != 0 ) { + d->imageFile.remove(); + emit infoMessage( i18n("Removed incomplete image file %1.").arg(d->imageFile.name()), WARNING ); + } + } + + if( m_canceled ) { + emit canceled(); + jobFinished(false); + } + else { + if( p->normalExit() ) { + if( p->exitStatus() == 0 ) { + jobFinished( !mkisofsReadError() ); + } + else { + switch( p->exitStatus() ) { + case 104: + // connection reset by peer + // This only happens if cdrecord does not finish successfully + // so we may leave the error handling to it meaning we handle this + // as a known error + break; + + case 2: + // mkisofs seems to have a bug that prevents to use filenames + // that contain one or more backslashes + // mkisofs 1.14 has the bug, 1.15a40 not + // TODO: find out the version that fixed the bug + if( m_containsFilesWithMultibleBackslashes && + !k3bcore->externalBinManager()->binObject( "mkisofs" )->hasFeature( "backslashed_filenames" ) ) { + emit infoMessage( i18n("Due to a bug in mkisofs <= 1.15a40, K3b is unable to handle " + "filenames that contain more than one backslash:"), ERROR ); + + break; + } + // otherwise just fall through + + default: + if( !d->knownError && !mkisofsReadError() ) { + emit infoMessage( i18n("%1 returned an unknown error (code %2).").arg("mkisofs").arg(p->exitStatus()), + K3bJob::ERROR ); + emit infoMessage( i18n("Please send me an email with the last output."), K3bJob::ERROR ); + } + } + + jobFinished( false ); + } + } + else { + emit infoMessage( i18n("%1 did not exit cleanly.").arg("mkisofs"), ERROR ); + jobFinished( false ); + } + } + + cleanup(); +} + + +void K3bIsoImager::cleanup() +{ + // remove all temp files + delete m_pathSpecFile; + delete m_rrHideFile; + delete m_jolietHideFile; + delete m_sortWeightFile; + + // remove boot-images-temp files + for( QStringList::iterator it = m_tempFiles.begin(); + it != m_tempFiles.end(); ++it ) + QFile::remove( *it ); + m_tempFiles.clear(); + + m_pathSpecFile = m_jolietHideFile = m_rrHideFile = m_sortWeightFile = 0; + + delete m_process; + m_process = 0; + + clearDummyDirs(); +} + + +void K3bIsoImager::init() +{ + jobStarted(); + + cleanup(); + + d->dataPreparationJob->start(); +} + + +void K3bIsoImager::slotDataPreparationDone( bool success ) +{ + if( success ) { + // + // We always calculate the image size. It does not take long and at least the mixed job needs it + // anyway + // + startSizeCalculation(); + } + else { + if( d->dataPreparationJob->hasBeenCanceled() ) { + m_canceled = true; + emit canceled(); + } + jobFinished( false ); + } +} + + +void K3bIsoImager::calculateSize() +{ + jobStarted(); + startSizeCalculation(); +} + + +void K3bIsoImager::startSizeCalculation() +{ + d->mkisofsBin = initMkisofs(); + if( !d->mkisofsBin ) { + jobFinished( false ); + return; + } + + initVariables(); + + delete m_process; + m_process = new K3bProcess(); + m_process->setRunPrivileged(true); + m_process->setSplitStdout(true); + + emit debuggingOutput( "Used versions", "mkisofs: " + d->mkisofsBin->version ); + + *m_process << d->mkisofsBin; + + if( !prepareMkisofsFiles() || + !addMkisofsParameters(true) ) { + cleanup(); + jobFinished( false ); + return; + } + + // add empty dummy dir since one path-spec is needed + // ??? Seems it is not needed after all. At least mkisofs 1.14 and above don't need it. ??? + // *m_process << dummyDir(); + + kdDebug() << "***** mkisofs calculate size parameters:\n"; + const QValueList& args = m_process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << endl << flush; + emit debuggingOutput("mkisofs calculate size command:", s); + + // since output changed during mkisofs version changes we grab both + // stdout and stderr + + // mkisofs version >= 1.15 (don't know about 1.14!) + // the extends on stdout (as lonely number) + // and error and warning messages on stderr + + // mkisofs >= 1.13 + // everything is written to stderr + // last line is: "Total extents scheduled to be written = XXXXX" + + // TODO: use K3bProcess::OutputCollector instead iof our own two slots. + + connect( m_process, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotCollectMkisofsPrintSizeStderr(KProcess*, char*, int)) ); + connect( m_process, SIGNAL(stdoutLine(const QString&)), + this, SLOT(slotCollectMkisofsPrintSizeStdout(const QString&)) ); + connect( m_process, SIGNAL(processExited(KProcess*)), + this, SLOT(slotMkisofsPrintSizeFinished()) ); + + // we also want error messages + connect( m_process, SIGNAL(stderrLine( const QString& )), + this, SLOT(slotReceivedStderr( const QString& )) ); + + m_collectedMkisofsPrintSizeStdout = QString::null; + m_collectedMkisofsPrintSizeStderr = QString::null; + m_mkisofsPrintSizeResult = 0; + + if( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) { + emit infoMessage( i18n("Could not start %1.").arg("mkisofs"), K3bJob::ERROR ); + cleanup(); + + jobFinished( false ); + return; + } +} + + +void K3bIsoImager::slotCollectMkisofsPrintSizeStderr(KProcess*, char* data , int len) +{ + emit debuggingOutput( "mkisofs", QString::fromLocal8Bit( data, len ) ); + m_collectedMkisofsPrintSizeStderr.append( QString::fromLocal8Bit( data, len ) ); +} + + +void K3bIsoImager::slotCollectMkisofsPrintSizeStdout( const QString& line ) +{ + // newer versions of mkisofs outut additional lines of junk before the size :( + // so we only use the last line + emit debuggingOutput( "mkisofs", line ); + m_collectedMkisofsPrintSizeStdout = line; +} + + +void K3bIsoImager::slotMkisofsPrintSizeFinished() +{ + if( m_canceled ) { + emit canceled(); + jobFinished( false ); + return; + } + + bool success = true; + + // if m_collectedMkisofsPrintSizeStdout is not empty we have a recent version of + // mkisofs and parsing is very easy (s.o.) + if( !m_collectedMkisofsPrintSizeStdout.isEmpty() ) { + kdDebug() << "(K3bIsoImager) iso size: " << m_collectedMkisofsPrintSizeStdout << endl; + m_mkisofsPrintSizeResult = m_collectedMkisofsPrintSizeStdout.toInt( &success ); + } + else { + // parse the stderr output + // I hope parsing the last line is enough! + int pos = m_collectedMkisofsPrintSizeStderr.findRev( "extents scheduled to be written" ); + + if( pos == -1 ) + success = false; + else + m_mkisofsPrintSizeResult = m_collectedMkisofsPrintSizeStderr.mid( pos+33 ).toInt( &success ); + } + + emit debuggingOutput( "K3bIsoImager", + QString("mkisofs print size result: %1 (%2 bytes)") + .arg(m_mkisofsPrintSizeResult) + .arg(Q_UINT64(m_mkisofsPrintSizeResult)*2048ULL) ); + + cleanup(); + + + if( success ) { + jobFinished( true ); + } + else { + m_mkisofsPrintSizeResult = 0; + kdDebug() << "(K3bIsoImager) Parsing mkisofs -print-size failed: " << m_collectedMkisofsPrintSizeStdout << endl; + emit infoMessage( i18n("Could not determine size of resulting image file."), ERROR ); + jobFinished( false ); + } +} + + +void K3bIsoImager::initVariables() +{ + m_containsFilesWithMultibleBackslashes = false; + m_processExited = false; + m_canceled = false; + d->knownError = false; + + // determine symlink handling + // follow links superseeds discard all links which superseeds discard broken links + // without rockridge we follow the links or discard all + if( m_doc->isoOptions().followSymbolicLinks() ) + d->usedLinkHandling = Private::FOLLOW; + else if( m_doc->isoOptions().discardSymlinks() ) + d->usedLinkHandling = Private::DISCARD_ALL; + else if( m_doc->isoOptions().createRockRidge() ) { + if( m_doc->isoOptions().discardBrokenSymlinks() ) + d->usedLinkHandling = Private::DISCARD_BROKEN; + else + d->usedLinkHandling = Private::KEEP_ALL; + } + else { + d->usedLinkHandling = Private::FOLLOW; + } + + m_sessionNumber = s_imagerSessionCounter++; +} + + +void K3bIsoImager::start() +{ + jobStarted(); + + cleanup(); + + d->mkisofsBin = initMkisofs(); + if( !d->mkisofsBin ) { + jobFinished( false ); + return; + } + + initVariables(); + + m_process = new K3bProcess(); + m_process->setRunPrivileged(true); + + *m_process << d->mkisofsBin; + + // prepare the filenames as written to the image + m_doc->prepareFilenames(); + + if( !prepareMkisofsFiles() || + !addMkisofsParameters() ) { + cleanup(); + jobFinished( false ); + return; + } + + connect( m_process, SIGNAL(processExited(KProcess*)), + this, SLOT(slotProcessExited(KProcess*)) ); + + connect( m_process, SIGNAL(stderrLine( const QString& )), + this, SLOT(slotReceivedStderr( const QString& )) ); + + // + // Check the image file + if( m_fdToWriteTo == -1 ) { + d->imageFile.setName( d->imagePath ); + if( !d->imageFile.open( IO_WriteOnly ) ) { + emit infoMessage( i18n("Could not open %1 for writing").arg(d->imagePath), ERROR ); + cleanup(); + jobFinished(false); + return; + } + } + + // + // Open the active pipe which does the streaming + delete d->pipe; + if( m_doc->verifyData() ) + d->pipe = new K3bChecksumPipe(); + else + d->pipe = new K3bActivePipe(); + + if( m_fdToWriteTo == -1 ) + d->pipe->writeToIODevice( &d->imageFile ); + else + d->pipe->writeToFd( m_fdToWriteTo ); + d->pipe->open(); + m_process->writeToFd( d->pipe->in() ); + + + kdDebug() << "***** mkisofs parameters:\n"; + const QValueList& args = m_process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << endl << flush; + emit debuggingOutput("mkisofs command:", s); + + if( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput) ) { + // something went wrong when starting the program + // it "should" be the executable + kdDebug() << "(K3bIsoImager) could not start mkisofs" << endl; + emit infoMessage( i18n("Could not start %1.").arg("mkisofs"), K3bJob::ERROR ); + jobFinished( false ); + cleanup(); + } +} + + +void K3bIsoImager::cancel() +{ + m_canceled = true; + + if( m_process && !m_processExited ) { + m_process->kill(); + } + else if( active() ) { + emit canceled(); + jobFinished(false); + } +} + + +void K3bIsoImager::setMultiSessionInfo( const QString& info, K3bDevice::Device* dev ) +{ + m_multiSessionInfo = info; + m_device = dev; +} + + +// iso9660 + RR use some latin1 variant. So we need to cut the desc fields +// counting 8bit chars. The GUI should take care of restricting the length +// and the charset +static void truncateTheHardWay( QString& s, int max ) +{ + QCString cs = s.utf8(); + cs.truncate(max); + s = QString::fromUtf8( cs ); +} + + +bool K3bIsoImager::addMkisofsParameters( bool printSize ) +{ + // add multisession info + if( !m_multiSessionInfo.isEmpty() ) { + *m_process << "-cdrecord-params" << m_multiSessionInfo; + if( m_device ) + *m_process << "-prev-session" << m_device->blockDeviceName(); + } + + // add the arguments + *m_process << "-gui"; + *m_process << "-graft-points"; + + if( printSize ) + *m_process << "-print-size" << "-quiet"; + + if( !m_doc->isoOptions().volumeID().isEmpty() ) { + QString s = m_doc->isoOptions().volumeID(); + truncateTheHardWay(s, 32); // ensure max length + *m_process << "-volid" << s; + } + else { + emit infoMessage( i18n("No volume id specified. Using default."), WARNING ); + *m_process << "-volid" << "CDROM"; + } + + QString s = m_doc->isoOptions().volumeSetId(); + truncateTheHardWay(s, 128); // ensure max length + *m_process << "-volset" << s; + + s = m_doc->isoOptions().applicationID(); + truncateTheHardWay(s, 128); // ensure max length + *m_process << "-appid" << s; + + s = m_doc->isoOptions().publisher(); + truncateTheHardWay(s, 128); // ensure max length + *m_process << "-publisher" << s; + + s = m_doc->isoOptions().preparer(); + truncateTheHardWay(s, 128); // ensure max length + *m_process << "-preparer" << s; + + s = m_doc->isoOptions().systemId(); + truncateTheHardWay(s, 32); // ensure max length + *m_process << "-sysid" << s; + + s = m_doc->isoOptions().abstractFile(); + truncateTheHardWay(s, 37); // ensure max length + if ( !s.isEmpty() ) + *m_process << "-abstract" << s; + + s = m_doc->isoOptions().copyrightFile(); + truncateTheHardWay(s, 37); // ensure max length + if ( !s.isEmpty() ) + *m_process << "-copyright" << s; + + s = m_doc->isoOptions().bibliographFile(); + truncateTheHardWay(s, 37); // ensure max length + if ( !s.isEmpty() ) + *m_process << "-biblio" << s; + + int volsetSize = m_doc->isoOptions().volumeSetSize(); + int volsetSeqNo = m_doc->isoOptions().volumeSetNumber(); + if( volsetSeqNo > volsetSize ) { + kdDebug() << "(K3bIsoImager) invalid volume set sequence number: " << volsetSeqNo + << " with volume set size: " << volsetSize << endl; + volsetSeqNo = volsetSize; + } + *m_process << "-volset-size" << QString::number(volsetSize); + *m_process << "-volset-seqno" << QString::number(volsetSeqNo); + + if( m_sortWeightFile ) { + *m_process << "-sort" << m_sortWeightFile->name(); + } + + if( m_doc->isoOptions().createRockRidge() ) { + if( m_doc->isoOptions().preserveFilePermissions() ) + *m_process << "-rock"; + else + *m_process << "-rational-rock"; + if( m_rrHideFile ) + *m_process << "-hide-list" << m_rrHideFile->name(); + } + + if( m_doc->isoOptions().createJoliet() ) { + *m_process << "-joliet"; + if( m_doc->isoOptions().jolietLong() ) + *m_process << "-joliet-long"; + if( m_jolietHideFile ) + *m_process << "-hide-joliet-list" << m_jolietHideFile->name(); + } + + if( m_doc->isoOptions().doNotCacheInodes() ) + *m_process << "-no-cache-inodes"; + + // + // Check if we have files > 2 GB and enable udf in that case. + // + bool filesGreaterThan2Gb = false; + K3bDataItem* item = m_doc->root(); + while( (item = item->nextSibling()) ) { + if( item->isFile() && item->size() > 2LL*1024LL*1024LL*1024LL ) { + filesGreaterThan2Gb = true; + break; + } + } + + if( filesGreaterThan2Gb ) { + emit infoMessage( i18n("Found files bigger than 2 GB. These files will only be fully accessible if mounted with UDF."), + WARNING ); + + // in genisoimage 1.1.3 "they" silently introduced this aweful parameter + if ( d->mkisofsBin->hasFeature( "genisoimage" ) && d->mkisofsBin->version >= K3bVersion( 1, 1, 3 ) ) { + *m_process << "-allow-limited-size"; + } + } + + bool udf = m_doc->isoOptions().createUdf(); + if( !udf && filesGreaterThan2Gb ) { + emit infoMessage( i18n("Enabling UDF extension."), INFO ); + udf = true; + } + if( udf ) + *m_process << "-udf"; + + if( m_doc->isoOptions().ISOuntranslatedFilenames() ) { + *m_process << "-untranslated-filenames"; + } + else { + if( m_doc->isoOptions().ISOallowPeriodAtBegin() ) + *m_process << "-allow-leading-dots"; + if( m_doc->isoOptions().ISOallow31charFilenames() ) + *m_process << "-full-iso9660-filenames"; + if( m_doc->isoOptions().ISOomitVersionNumbers() && !m_doc->isoOptions().ISOmaxFilenameLength() ) + *m_process << "-omit-version-number"; + if( m_doc->isoOptions().ISOrelaxedFilenames() ) + *m_process << "-relaxed-filenames"; + if( m_doc->isoOptions().ISOallowLowercase() ) + *m_process << "-allow-lowercase"; + if( m_doc->isoOptions().ISOnoIsoTranslate() ) + *m_process << "-no-iso-translate"; + if( m_doc->isoOptions().ISOallowMultiDot() ) + *m_process << "-allow-multidot"; + if( m_doc->isoOptions().ISOomitTrailingPeriod() ) + *m_process << "-omit-period"; + } + + if( m_doc->isoOptions().ISOmaxFilenameLength() ) + *m_process << "-max-iso9660-filenames"; + + if( m_noDeepDirectoryRelocation ) + *m_process << "-disable-deep-relocation"; + + // We do our own following +// if( m_doc->isoOptions().followSymbolicLinks() || !m_doc->isoOptions().createRockRidge() ) +// *m_process << "-follow-links"; + + if( m_doc->isoOptions().createTRANS_TBL() ) + *m_process << "-translation-table"; + if( m_doc->isoOptions().hideTRANS_TBL() ) + *m_process << "-hide-joliet-trans-tbl"; + + *m_process << "-iso-level" << QString::number(m_doc->isoOptions().ISOLevel()); + + if( m_doc->isoOptions().forceInputCharset() ) + *m_process << "-input-charset" << m_doc->isoOptions().inputCharset(); + + *m_process << "-path-list" << QFile::encodeName(m_pathSpecFile->name()); + + + // boot stuff + if( !m_doc->bootImages().isEmpty() ) { + bool first = true; + for( QPtrListIterator it( m_doc->bootImages() ); + *it; ++it ) { + if( !first ) + *m_process << "-eltorito-alt-boot"; + + K3bBootItem* bootItem = *it; + + *m_process << "-eltorito-boot"; + *m_process << bootItem->writtenPath(); + + if( bootItem->imageType() == K3bBootItem::HARDDISK ) { + *m_process << "-hard-disk-boot"; + } + else if( bootItem->imageType() == K3bBootItem::NONE ) { + *m_process << "-no-emul-boot"; + if( bootItem->loadSegment() > 0 ) + *m_process << "-boot-load-seg" << QString::number(bootItem->loadSegment()); + if( bootItem->loadSize() > 0 ) + *m_process << "-boot-load-size" << QString::number(bootItem->loadSize()); + } + + if( bootItem->imageType() != K3bBootItem::NONE && bootItem->noBoot() ) + *m_process << "-no-boot"; + if( bootItem->bootInfoTable() ) + *m_process << "-boot-info-table"; + + first = false; + } + + *m_process << "-eltorito-catalog" << m_doc->bootCataloge()->writtenPath(); + } + + + // additional parameters from config + const QStringList& params = k3bcore->externalBinManager()->binObject( "mkisofs" )->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *m_process << *it; + + return true; +} + + +int K3bIsoImager::writePathSpec() +{ + delete m_pathSpecFile; + m_pathSpecFile = new KTempFile(); + m_pathSpecFile->setAutoDelete(true); + + if( QTextStream* t = m_pathSpecFile->textStream() ) { + // recursive path spec writing + int num = writePathSpecForDir( m_doc->root(), *t ); + + m_pathSpecFile->close(); + + return num; + } + else + return -1; +} + + +int K3bIsoImager::writePathSpecForDir( K3bDirItem* dirItem, QTextStream& stream ) +{ + if( !m_noDeepDirectoryRelocation && dirItem->depth() > 7 ) { + kdDebug() << "(K3bIsoImager) found directory depth > 7. Enabling no deep directory relocation." << endl; + m_noDeepDirectoryRelocation = true; + } + + // now create the graft points + int num = 0; + for( QPtrListIterator it( dirItem->children() ); it.current(); ++it ) { + K3bDataItem* item = it.current(); + bool writeItem = item->writeToCd(); + + if( item->isSymLink() ) { + if( d->usedLinkHandling == Private::DISCARD_ALL || + ( d->usedLinkHandling == Private::DISCARD_BROKEN && + !item->isValid() ) ) + writeItem = false; + + else if( d->usedLinkHandling == Private::FOLLOW ) { + QFileInfo f( K3b::resolveLink( item->localPath() ) ); + if( !f.exists() ) { + emit infoMessage( i18n("Could not follow link %1 to non-existing file %2. Skipping...") + .arg(item->k3bName()) + .arg(f.filePath()), WARNING ); + writeItem = false; + } + else if( f.isDir() ) { + emit infoMessage( i18n("Ignoring link %1 to folder %2. K3b is unable to follow links to folders.") + .arg(item->k3bName()) + .arg(f.filePath()), WARNING ); + writeItem = false; + } + } + } + else if( item->isFile() ) { + QFileInfo f( item->localPath() ); + if( !f.exists() ) { + emit infoMessage( i18n("Could not find file %1. Skipping...").arg(item->localPath()), WARNING ); + writeItem = false; + } + else if( !f.isReadable() ) { + emit infoMessage( i18n("Could not read file %1. Skipping...").arg(item->localPath()), WARNING ); + writeItem = false; + } + } + + if( writeItem ) { + num++; + + // some versions of mkisofs seem to have a bug that prevents to use filenames + // that contain one or more backslashes + if( item->writtenPath().contains("\\") ) + m_containsFilesWithMultibleBackslashes = true; + + + if( item->isDir() ) { + stream << escapeGraftPoint( item->writtenPath() ) + << "=" + << escapeGraftPoint( dummyDir( static_cast(item) ) ) << "\n"; + + int x = writePathSpecForDir( dynamic_cast(item), stream ); + if( x >= 0 ) + num += x; + else + return -1; + } + else { + writePathSpecForFile( static_cast(item), stream ); + } + } + } + + return num; +} + + +void K3bIsoImager::writePathSpecForFile( K3bFileItem* item, QTextStream& stream ) +{ + stream << escapeGraftPoint( item->writtenPath() ) + << "="; + + if( m_doc->bootImages().containsRef( dynamic_cast(item) ) ) { // boot-image-backup-hack + + // create temp file + KTempFile temp; + QString tempPath = temp.name(); + temp.unlink(); + + if( !KIO::NetAccess::copy( KURL(item->localPath()), KURL::fromPathOrURL(tempPath) ) ) { + emit infoMessage( i18n("Failed to backup boot image file %1").arg(item->localPath()), ERROR ); + return; + } + + static_cast(item)->setTempPath( tempPath ); + + m_tempFiles.append(tempPath); + stream << escapeGraftPoint( tempPath ) << "\n"; + } + else if( item->isSymLink() && d->usedLinkHandling == Private::FOLLOW ) + stream << escapeGraftPoint( K3b::resolveLink( item->localPath() ) ) << "\n"; + else + stream << escapeGraftPoint( item->localPath() ) << "\n"; +} + + +bool K3bIsoImager::writeRRHideFile() +{ + delete m_rrHideFile; + m_rrHideFile = new KTempFile(); + m_rrHideFile->setAutoDelete(true); + + if( QTextStream* t = m_rrHideFile->textStream() ) { + + K3bDataItem* item = m_doc->root(); + while( item ) { + if( item->hideOnRockRidge() ) { + if( !item->isDir() ) // hiding directories does not work (all dirs point to the dummy-dir) + *t << escapeGraftPoint( item->localPath() ) << endl; + } + item = item->nextSibling(); + } + + m_rrHideFile->close(); + return true; + } + else + return false; +} + + +bool K3bIsoImager::writeJolietHideFile() +{ + delete m_jolietHideFile; + m_jolietHideFile = new KTempFile(); + m_jolietHideFile->setAutoDelete(true); + + if( QTextStream* t = m_jolietHideFile->textStream() ) { + + K3bDataItem* item = m_doc->root(); + while( item ) { + if( item->hideOnRockRidge() ) { + if( !item->isDir() ) // hiding directories does not work (all dirs point to the dummy-dir but we could introduce a second hidden dummy dir) + *t << escapeGraftPoint( item->localPath() ) << endl; + } + item = item->nextSibling(); + } + + m_jolietHideFile->close(); + return true; + } + else + return false; +} + + +bool K3bIsoImager::writeSortWeightFile() +{ + delete m_sortWeightFile; + m_sortWeightFile = new KTempFile(); + m_sortWeightFile->setAutoDelete(true); + + if( QTextStream* t = m_sortWeightFile->textStream() ) { + // + // We need to write the local path in combination with the sort weight + // mkisofs will take care of multiple entries for one local file and always + // use the highest weight + // + K3bDataItem* item = m_doc->root(); + while( (item = item->nextSibling()) ) { // we skip the root here + if( item->sortWeight() != 0 ) { + if( m_doc->bootImages().containsRef( dynamic_cast(item) ) ) { // boot-image-backup-hack + *t << escapeGraftPoint( static_cast(item)->tempPath() ) << " " << item->sortWeight() << endl; + } + else if( item->isDir() ) { + // + // Since we use dummy dirs for all directories in the filesystem and mkisofs uses the local path + // for sorting we need to create a different dummy dir for every sort weight value. + // + *t << escapeGraftPoint( dummyDir( static_cast(item) ) ) << " " << item->sortWeight() << endl; + } + else + *t << escapeGraftPoint( item->localPath() ) << " " << item->sortWeight() << endl; + } + } + + m_sortWeightFile->close(); + return true; + } + else + return false; +} + + +QString K3bIsoImager::escapeGraftPoint( const QString& str ) +{ + QString enc = str; + + // + // mkisofs manpage (-graft-points) is incorrect (as of mkisofs 2.01.01) + // + // Actually an equal sign needs to be escaped with one backslash only + // Single backslashes inside a filename can be used without change + // while single backslashes at the end of a filename need to be escaped + // with two backslashes. + // + // There is one more problem though: the name in the iso tree can never + // in any number of backslashes. mkisofs simply cannot handle it. So we + // need to remove these slashes somewhere or ignore those files (we do + // that in K3bDataDoc::addUrls) + // + + // + // we do not use QString::replace to have full control + // this might be slow since QString::insert is slow but we don't care + // since this is only called to prepare the iso creation which is not + // time critical. :) + // + + unsigned int pos = 0; + while( pos < enc.length() ) { + // escape every equal sign with one backslash + if( enc[pos] == '=' ) { + enc.insert( pos, "\\" ); + pos += 2; + } + else if( enc[pos] == '\\' ) { + // escape every occurrence of two backslashes with two backslashes + if( pos+1 < enc.length() && enc[pos+1] == '\\' ) { + enc.insert( pos, "\\\\" ); + pos += 4; + } + // escape the last single backslash in the filename (see above) + else if( pos == enc.length()-1 ) { + enc.insert( pos, "\\" ); + pos += 2; + } + else + ++pos; + } + else + ++pos; + } + +// enc.replace( "\\\\", "\\\\\\\\" ); +// enc.replace( "=", "\\=" ); + + return enc; +} + + +bool K3bIsoImager::prepareMkisofsFiles() +{ + // write path spec file + // ---------------------------------------------------- + int num = writePathSpec(); + if( num < 0 ) { + emit infoMessage( i18n("Could not write temporary file"), K3bJob::ERROR ); + return false; + } + else if( num == 0 ) { + emit infoMessage( i18n("No files to be written."), K3bJob::ERROR ); + return false; + } + + if( m_doc->isoOptions().createRockRidge() ) { + if( !writeRRHideFile() ) { + emit infoMessage( i18n("Could not write temporary file"), K3bJob::ERROR ); + return false; + } + } + + if( m_doc->isoOptions().createJoliet() ) { + if( !writeJolietHideFile() ) { + emit infoMessage( i18n("Could not write temporary file"), K3bJob::ERROR ); + return false ; + } + } + + if( !writeSortWeightFile() ) { + emit infoMessage( i18n("Could not write temporary file"), K3bJob::ERROR ); + return false; + } + + return true; +} + + +QString K3bIsoImager::dummyDir( K3bDirItem* dir ) +{ + // + // since we use virtual folders in order to have folders with different weight factors and different + // permissions we create different dummy dirs to be passed to mkisofs + // + + QDir _appDir( locateLocal( "appdata", "temp/" ) ); + + // + // create a unique isoimager session id + // This might become important in case we will allow multiple instances of the isoimager + // to run at the same time. + // + QString jobId = qApp->sessionId() + "_" + QString::number( m_sessionNumber ); + + if( !_appDir.cd( jobId ) ) { + _appDir.mkdir( jobId ); + _appDir.cd( jobId ); + } + + QString name( "dummydir_" ); + name += QString::number( dir->sortWeight() ); + + bool perm = false; + k3b_struct_stat statBuf; + if( !dir->localPath().isEmpty() ) { + // permissions + if( k3b_stat( QFile::encodeName(dir->localPath()), &statBuf ) == 0 ) { + name += "_"; + name += QString::number( statBuf.st_uid ); + name += "_"; + name += QString::number( statBuf.st_gid ); + name += "_"; + name += QString::number( statBuf.st_mode ); + name += "_"; + name += QString::number( statBuf.st_mtime ); + + perm = true; + } + } + + + if( !_appDir.cd( name ) ) { + + kdDebug() << "(K3bIsoImager) creating dummy dir: " << _appDir.absPath() << "/" << name << endl; + + _appDir.mkdir( name ); + _appDir.cd( name ); + + if( perm ) { + ::chmod( QFile::encodeName( _appDir.absPath() ), statBuf.st_mode ); + ::chown( QFile::encodeName( _appDir.absPath() ), statBuf.st_uid, statBuf.st_gid ); + struct utimbuf tb; + tb.actime = tb.modtime = statBuf.st_mtime; + ::utime( QFile::encodeName( _appDir.absPath() ), &tb ); + } + } + + return _appDir.absPath() + "/"; +} + + +void K3bIsoImager::clearDummyDirs() +{ + QString jobId = qApp->sessionId() + "_" + QString::number( m_sessionNumber ); + QDir appDir( locateLocal( "appdata", "temp/" ) ); + if( appDir.cd( jobId ) ) { + QStringList dummyDirEntries = appDir.entryList( "dummydir*", QDir::Dirs ); + for( QStringList::iterator it = dummyDirEntries.begin(); it != dummyDirEntries.end(); ++it ) + appDir.rmdir( *it ); + appDir.cdUp(); + appDir.rmdir( jobId ); + } +} + + +QCString K3bIsoImager::checksum() const +{ + if( K3bChecksumPipe* p = dynamic_cast( d->pipe ) ) + return p->checksum(); + else + return QCString(); +} + + +bool K3bIsoImager::hasBeenCanceled() const +{ + return m_canceled; +} + +#include "k3bisoimager.moc" diff --git a/libk3b/projects/datacd/k3bisoimager.h b/libk3b/projects/datacd/k3bisoimager.h new file mode 100644 index 0000000..82501ba --- /dev/null +++ b/libk3b/projects/datacd/k3bisoimager.h @@ -0,0 +1,188 @@ +/* + * + * $Id: k3bisoimager.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_ISO_IMAGER_H +#define K3B_ISO_IMAGER_H + +#include +#include "k3bmkisofshandler.h" + +#include +#include + +class K3bDataDoc; +class K3bDirItem; +class K3bDataItem; +class K3bFileItem; +class QTextStream; +class K3bProcess; +class KProcess; +class K3bDevice::Device; +class KTempFile; + + +class K3bIsoImager : public K3bJob, public K3bMkisofsHandler +{ + Q_OBJECT + + public: + K3bIsoImager( K3bDataDoc*, K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + virtual ~K3bIsoImager(); + + virtual bool active() const; + + int size() const { return m_mkisofsPrintSizeResult; } + + virtual bool hasBeenCanceled() const; + + /** + * Get the checksum calculated during the creation of the image. + */ + QCString checksum() const; + + public slots: + /** + * Starts the actual image creation. Always run init() + * before starting the image creation + */ + virtual void start(); + virtual void cancel(); + + /** + * Initialize the image creator. This calculates the image size and performs + * some checks on the project. + * + * The initialization process also finishes with the finished() signal just + * like a normal job operation. Get the calculated image size via size() + */ + virtual void init(); + + /** + * Only calculates the size of the image without the additional checks in + * init() + * + * Use this if you need to recalculate the image size for example if the + * multisession info changed. + */ + virtual void calculateSize(); + + /** + * lets the isoimager write directly into fd instead of writing + * to an image file. + * Be aware that this only makes sense before starting the job. + * To disable just set @p fd to -1 + */ + void writeToFd( int fd ); + + void writeToImageFile( const QString& path ); + + /** + * If dev == 0 K3bIsoImager will ignore the data in the previous session. + * This is usable for CD-Extra. + */ + void setMultiSessionInfo( const QString&, K3bDevice::Device* dev = 0 ); + + K3bDevice::Device* device() const { return m_device; } + K3bDataDoc* doc() const { return m_doc; } + + protected: + virtual void handleMkisofsProgress( int ); + virtual void handleMkisofsInfoMessage( const QString&, int ); + + virtual bool addMkisofsParameters( bool printSize = false ); + + /** + * calls writePathSpec, writeRRHideFile, and writeJolietHideFile + */ + bool prepareMkisofsFiles(); + + /** + * The dummy dir is used to create dirs on the iso-filesystem. + * + * @return an empty dummy dir for use with K3bDirItems. + */ + QString dummyDir( K3bDirItem* ); + + void outputData(); + void initVariables(); + virtual void cleanup(); + void clearDummyDirs(); + + /** + * @returns The number of entries written or -1 on error + */ + virtual int writePathSpec(); + bool writeRRHideFile(); + bool writeJolietHideFile(); + bool writeSortWeightFile(); + + // used by writePathSpec + virtual int writePathSpecForDir( K3bDirItem* dirItem, QTextStream& stream ); + virtual void writePathSpecForFile( K3bFileItem*, QTextStream& stream ); + QString escapeGraftPoint( const QString& str ); + + KTempFile* m_pathSpecFile; + KTempFile* m_rrHideFile; + KTempFile* m_jolietHideFile; + KTempFile* m_sortWeightFile; + + K3bProcess* m_process; + + bool m_processExited; + bool m_canceled; + + protected slots: + virtual void slotReceivedStderr( const QString& ); + virtual void slotProcessExited( KProcess* ); + + private slots: + void slotCollectMkisofsPrintSizeStderr(KProcess*, char*, int); + void slotCollectMkisofsPrintSizeStdout( const QString& ); + void slotMkisofsPrintSizeFinished(); + void slotDataPreparationDone( bool success ); + + private: + void startSizeCalculation(); + + class Private; + Private* d; + + K3bDataDoc* m_doc; + + bool m_noDeepDirectoryRelocation; + + bool m_importSession; + QString m_multiSessionInfo; + K3bDevice::Device* m_device; + + // used for mkisofs -print-size parsing + QString m_collectedMkisofsPrintSizeStdout; + QString m_collectedMkisofsPrintSizeStderr; + int m_mkisofsPrintSizeResult; + + QStringList m_tempFiles; + + int m_fdToWriteTo; + + bool m_containsFilesWithMultibleBackslashes; + + // used to create a unique session id + static int s_imagerSessionCounter; + + int m_sessionNumber; +}; + + +#endif diff --git a/libk3b/projects/datacd/k3bisooptions.cpp b/libk3b/projects/datacd/k3bisooptions.cpp new file mode 100644 index 0000000..bd7314d --- /dev/null +++ b/libk3b/projects/datacd/k3bisooptions.cpp @@ -0,0 +1,216 @@ +/* + * + * $Id: k3bisooptions.cpp 639665 2007-03-05 16:29:52Z trueg $ + * Copyright (C) 2003-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bisooptions.h" +#include +#include +#include + +#include +#include +#include + + +K3bIsoOptions::K3bIsoOptions() + : m_volumeID( "K3b data project" ), + m_applicationID( QString("K3B THE CD KREATOR (C) 1998-2006 SEBASTIAN TRUEG AND THE K3B TEAM") ), + m_systemId( K3b::systemName().upper() ), + m_inputCharset( "iso8859-1" ), + m_whiteSpaceTreatmentReplaceString( "_" ) +{ + m_bForceInputCharset = false; + + m_createRockRidge = true; + m_createJoliet = true; + m_createUdf = false; + m_ISOallowLowercase = false; + m_ISOallowPeriodAtBegin = false; + m_ISOallow31charFilenames = true; + m_ISOomitVersionNumbers = false; + m_ISOomitTrailingPeriod = false; + m_ISOmaxFilenameLength = false; + m_ISOrelaxedFilenames = false; + m_ISOnoIsoTranslate = false; + m_ISOallowMultiDot = false; + m_ISOuntranslatedFilenames = false; + m_followSymbolicLinks = false; + m_createTRANS_TBL = false; + m_hideTRANS_TBL = false; + m_jolietLong = true; + + m_doNotCacheInodes = true; + + m_isoLevel = 2; + + m_discardSymlinks = false; + m_discardBrokenSymlinks = false; + + m_preserveFilePermissions = false; + + m_whiteSpaceTreatment = noChange; + + m_volumeSetSize = 1; + m_volumeSetNumber = 1; +} + + +void K3bIsoOptions::save( KConfigBase* c, bool saveVolumeDesc ) +{ + if( saveVolumeDesc ) { + c->writeEntry( "volume id", m_volumeID ); + c->writeEntry( "application id", m_applicationID ); + c->writeEntry( "preparer", m_preparer ); + c->writeEntry( "publisher", m_publisher ); + c->writeEntry( "system id", m_systemId ); + c->writeEntry( "volume set id", m_volumeSetId ); + c->writeEntry( "volume set size", m_volumeSetSize ); + c->writeEntry( "volume set number", m_volumeSetNumber ); + c->writeEntry( "abstract file", m_abstractFile ); + c->writeEntry( "copyright file", m_copyrightFile ); + c->writeEntry( "bibliograph file", m_bibliographFile ); + } + + c->writeEntry( "rock_ridge", m_createRockRidge ); + c->writeEntry( "joliet", m_createJoliet ); + c->writeEntry( "udf", m_createUdf ); + + // save iso-level + c->writeEntry( "iso_level", m_isoLevel ); + + c->writeEntry( "create TRANS_TBL", m_createTRANS_TBL ); + c->writeEntry( "hide TRANS_TBL", m_hideTRANS_TBL ); + c->writeEntry( "untranslated filenames", m_ISOuntranslatedFilenames ); + c->writeEntry( "allow 31 character filenames", m_ISOallow31charFilenames ); + c->writeEntry( "max ISO filenames", m_ISOmaxFilenameLength ); + c->writeEntry( "allow beginning period", m_ISOallowPeriodAtBegin ); + c->writeEntry( "relaxed filenames", m_ISOrelaxedFilenames ); + c->writeEntry( "omit version numbers", m_ISOomitVersionNumbers ); + c->writeEntry( "omit trailing period", m_ISOomitTrailingPeriod ); + c->writeEntry( "no iSO translation", m_ISOnoIsoTranslate ); + c->writeEntry( "allow multiple dots", m_ISOallowMultiDot ); + c->writeEntry( "allow lowercase filenames", m_ISOallowLowercase ); + // c->writeEntry( "follow symbolic links", m_followSymbolicLinks ); + + c->writeEntry( "joliet long", m_jolietLong ); + + c->writeEntry( "force input charset", m_bForceInputCharset ); + c->writeEntry( "input charset", m_inputCharset ); + + c->writeEntry( "do not cache inodes", m_doNotCacheInodes ); + + // save whitespace-treatment + switch( m_whiteSpaceTreatment ) { + case strip: + c->writeEntry( "white_space_treatment", "strip" ); + break; + case extended: + c->writeEntry( "white_space_treatment", "extended" ); + break; + case replace: + c->writeEntry( "white_space_treatment", "replace" ); + break; + default: + c->writeEntry( "white_space_treatment", "noChange" ); + } + + c->writeEntry( "whitespace replace string", m_whiteSpaceTreatmentReplaceString ); + + c->writeEntry( "discard symlinks", discardSymlinks() ); + c->writeEntry( "discard broken symlinks", discardBrokenSymlinks() ); + + c->writeEntry( "preserve file permissions", m_preserveFilePermissions ); +} + + +K3bIsoOptions K3bIsoOptions::load( KConfigBase* c, bool loadVolumeDesc ) +{ + K3bIsoOptions options; + + if( loadVolumeDesc ) { + options.setVolumeID( c->readEntry( "volume id", options.volumeID() ) ); + options.setApplicationID( c->readEntry( "application id", options.applicationID() ) ); + options.setPreparer( c->readEntry( "preparer", options.preparer() ) ); + options.setPublisher( c->readEntry( "publisher", options.publisher() ) ); + options.setSystemId( c->readEntry( "system id", options.systemId() ) ); + options.setVolumeSetId( c->readEntry( "volume set id", options.volumeSetId() ) ); + options.setVolumeSetSize( c->readNumEntry( "volume set size", options.volumeSetSize() ) ); + options.setVolumeSetNumber( c->readNumEntry( "volume set number", options.volumeSetNumber() ) ); + options.setAbstractFile( c->readEntry( "abstract file", options.abstractFile() ) ); + options.setCoprightFile( c->readEntry( "copyright file", options.copyrightFile() ) ); + options.setBibliographFile( c->readEntry( "bibliograph file", options.bibliographFile() ) ); + } + + options.setForceInputCharset( c->readBoolEntry( "force input charset", options.forceInputCharset() ) ); + if( options.forceInputCharset() ) + options.setInputCharset( c->readEntry( "input charset", options.inputCharset() ) ); + + options.setCreateRockRidge( c->readBoolEntry( "rock_ridge", options.createRockRidge() ) ); + options.setCreateJoliet( c->readBoolEntry( "joliet", options.createJoliet() ) ); + options.setCreateUdf( c->readBoolEntry( "udf", options.createUdf() ) ); + + options.setISOLevel( c->readNumEntry( "iso_level", options.ISOLevel() ) ); + + options.setCreateTRANS_TBL( c->readBoolEntry( "create TRANS_TBL", options.createTRANS_TBL() ) ); + options.setHideTRANS_TBL( c->readBoolEntry( "hide TRANS_TBL", options.hideTRANS_TBL() ) ); + + // + // We need to use the memeber variables here instead of the access methods + // which do not return the actual value of the member variables but the value + // representing the use in mkisofs (i.e. ISOomitVersionNumbers is also enabled + // if ISOmaxFilenameLength is enabled. + // + options.setISOuntranslatedFilenames( c->readBoolEntry( "untranslated filenames", options.m_ISOuntranslatedFilenames ) ); + options.setISOallow31charFilenames( c->readBoolEntry( "allow 31 character filenames", options.m_ISOallow31charFilenames ) ); + options.setISOmaxFilenameLength( c->readBoolEntry( "max ISO filenames", options.m_ISOmaxFilenameLength ) ); + options.setISOallowPeriodAtBegin( c->readBoolEntry( "allow beginning period", options.m_ISOallowPeriodAtBegin ) ); + options.setISOrelaxedFilenames( c->readBoolEntry( "relaxed filenames", options.m_ISOrelaxedFilenames ) ); + options.setISOomitVersionNumbers( c->readBoolEntry( "omit version numbers", options.m_ISOomitVersionNumbers ) ); + options.setISOnoIsoTranslate( c->readBoolEntry( "no iSO translation", options.m_ISOnoIsoTranslate ) ); + options.setISOallowMultiDot( c->readBoolEntry( "allow multiple dots", options.m_ISOallowMultiDot ) ); + options.setISOallowLowercase( c->readBoolEntry( "allow lowercase filenames", options.m_ISOallowLowercase ) ); + options.setISOomitTrailingPeriod( c->readBoolEntry( "omit trailing period", options.m_ISOomitTrailingPeriod ) ); + + // options.setFollowSymbolicLinks( c->readBoolEntry( "follow symbolic links", options.m_followSymbolicLinks ) ); + + options.setJolietLong( c->readBoolEntry( "joliet long", options.jolietLong() ) ); + + options.setDoNotCacheInodes( c->readBoolEntry( "do not cache inodes", options.doNotCacheInodes() ) ); + + QString w = c->readEntry( "white_space_treatment", "noChange" ); + if( w == "replace" ) + options.setWhiteSpaceTreatment( replace ); + else if( w == "strip" ) + options.setWhiteSpaceTreatment( strip ); + else if( w == "extended" ) + options.setWhiteSpaceTreatment( extended ); + else + options.setWhiteSpaceTreatment( noChange ); + + options.setWhiteSpaceTreatmentReplaceString( c->readEntry( "whitespace replace string", options.whiteSpaceTreatmentReplaceString() ) ); + + options.setDiscardSymlinks( c->readBoolEntry("discard symlinks", options.discardSymlinks() ) ); + options.setDiscardBrokenSymlinks( c->readBoolEntry("discard broken symlinks", options.discardBrokenSymlinks() ) ); + + options.setPreserveFilePermissions( c->readBoolEntry( "preserve file permissions", options.preserveFilePermissions() ) ); + + return options; +} + + +K3bIsoOptions K3bIsoOptions::defaults() +{ + // let the constructor create defaults + return K3bIsoOptions(); +} diff --git a/libk3b/projects/datacd/k3bisooptions.h b/libk3b/projects/datacd/k3bisooptions.h new file mode 100644 index 0000000..254c998 --- /dev/null +++ b/libk3b/projects/datacd/k3bisooptions.h @@ -0,0 +1,183 @@ +/* + * + * $Id: k3bisooptions.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_ISO_OPTIONS_H +#define K3B_ISO_OPTIONS_H + +#include +#include "k3b_export.h" + +class KConfigBase; + + +class LIBK3B_EXPORT K3bIsoOptions +{ + public: + K3bIsoOptions(); + + bool forceInputCharset() const { return m_bForceInputCharset; } + const QString& inputCharset() const { return m_inputCharset; } + + void setForceInputCharset( bool b ) { m_bForceInputCharset = b; } + void setInputCharset( const QString& cs ) { m_inputCharset = cs; } + + + // -- mkisofs-options ---------------------------------------------------------------------- + bool createRockRidge() const { return m_createRockRidge; } + bool createJoliet() const { return m_createJoliet; } + bool createUdf() const { return m_createUdf; } + bool ISOallowLowercase() const { return m_ISOallowLowercase || ISOuntranslatedFilenames(); } + bool ISOallowPeriodAtBegin() const { return m_ISOallowPeriodAtBegin || ISOuntranslatedFilenames(); } + bool ISOallow31charFilenames() const { return m_ISOallow31charFilenames || ISOmaxFilenameLength() || ISOuntranslatedFilenames(); } + bool ISOomitVersionNumbers() const { return m_ISOomitVersionNumbers || ISOmaxFilenameLength(); } + bool ISOomitTrailingPeriod() const { return m_ISOomitTrailingPeriod || ISOuntranslatedFilenames(); } + bool ISOmaxFilenameLength() const { return m_ISOmaxFilenameLength || ISOuntranslatedFilenames(); } + bool ISOrelaxedFilenames() const { return m_ISOrelaxedFilenames || ISOuntranslatedFilenames(); } + bool ISOnoIsoTranslate() const { return m_ISOnoIsoTranslate; } + bool ISOallowMultiDot() const { return m_ISOallowMultiDot || ISOuntranslatedFilenames(); } + bool ISOuntranslatedFilenames() const { return m_ISOuntranslatedFilenames; } + bool followSymbolicLinks() const { return m_followSymbolicLinks; } + bool createTRANS_TBL() const { return m_createTRANS_TBL; } + bool hideTRANS_TBL() const { return m_hideTRANS_TBL; } + bool jolietLong() const { return m_jolietLong; } + + bool preserveFilePermissions() const { return m_preserveFilePermissions; } + + int ISOLevel() const { return m_isoLevel; } + const QString& systemId() const { return m_systemId; } + const QString& applicationID() const { return m_applicationID; } + const QString& volumeID() const { return m_volumeID; } + const QString& volumeSetId() const { return m_volumeSetId; } + int volumeSetSize() const { return m_volumeSetSize; } + int volumeSetNumber() const { return m_volumeSetNumber; } + const QString& publisher() const { return m_publisher; } + const QString& preparer() const { return m_preparer; } + const QString& abstractFile() const { return m_abstractFile; } + const QString& copyrightFile() const { return m_copyrightFile; } + const QString& bibliographFile() const { return m_bibliographFile; } + + void setCreateRockRidge( bool b ) { m_createRockRidge = b; } + void setCreateJoliet( bool b ) { m_createJoliet = b; } + void setCreateUdf( bool b ) { m_createUdf = b; } + void setISOallowLowercase( bool b ) { m_ISOallowLowercase = b; } + void setISOallowPeriodAtBegin( bool b ) { m_ISOallowPeriodAtBegin = b; } + void setISOallow31charFilenames( bool b ) { m_ISOallow31charFilenames = b; } + void setISOomitVersionNumbers( bool b ) { m_ISOomitVersionNumbers = b; } + void setISOomitTrailingPeriod( bool b ) { m_ISOomitTrailingPeriod = b; } + void setISOmaxFilenameLength( bool b ) { m_ISOmaxFilenameLength = b; } + void setISOrelaxedFilenames( bool b ) { m_ISOrelaxedFilenames = b; } + void setISOnoIsoTranslate( bool b ) { m_ISOnoIsoTranslate = b; } + void setISOallowMultiDot( bool b ) { m_ISOallowMultiDot = b; } + void setISOuntranslatedFilenames( bool b ) { m_ISOuntranslatedFilenames = b; } + void setFollowSymbolicLinks( bool b ) { m_followSymbolicLinks = b; } + void setCreateTRANS_TBL( bool b ) { m_createTRANS_TBL = b; } + void setHideTRANS_TBL( bool b ) { m_hideTRANS_TBL = b; } + void setJolietLong( bool b ) { m_jolietLong = b; } + + void setISOLevel( int i ) { m_isoLevel = i; } + void setSystemId( const QString& s ) { m_systemId = s; } + void setApplicationID( const QString& s ) { m_applicationID = s; } + + /** + * Set the filesystems volume id. + * + * max length for this field is 32 chars. + */ + void setVolumeID( const QString& s ) { m_volumeID = s; } + void setVolumeSetId( const QString& s ) { m_volumeSetId = s; } + void setVolumeSetSize( int size ) { m_volumeSetSize = size; } + void setVolumeSetNumber( int n ) { m_volumeSetNumber = n; } + void setPublisher( const QString& s ) { m_publisher = s; } + void setPreparer( const QString& s ) { m_preparer = s; } + void setAbstractFile( const QString& s ) { m_abstractFile = s; } + void setCoprightFile( const QString& s ) { m_copyrightFile = s; } + void setBibliographFile( const QString& s ) { m_bibliographFile = s; } + + void setPreserveFilePermissions( bool b ) { m_preserveFilePermissions = b; } + // ----------------------------------------------------------------- mkisofs-options ----------- + + enum whiteSpaceTreatments { noChange = 0, replace = 1, strip = 2, extended = 3 }; + + void setWhiteSpaceTreatment( int i ) { m_whiteSpaceTreatment = i; } + int whiteSpaceTreatment() const { return m_whiteSpaceTreatment; } + const QString& whiteSpaceTreatmentReplaceString() const { return m_whiteSpaceTreatmentReplaceString; } + void setWhiteSpaceTreatmentReplaceString( const QString& s ) { m_whiteSpaceTreatmentReplaceString = s; } + + bool discardSymlinks() const { return m_discardSymlinks; } + void setDiscardSymlinks( bool b ) { m_discardSymlinks = b; } + + bool discardBrokenSymlinks() const { return m_discardBrokenSymlinks; } + void setDiscardBrokenSymlinks( bool b ) { m_discardBrokenSymlinks = b; } + + bool doNotCacheInodes() const { return m_doNotCacheInodes; } + void setDoNotCacheInodes( bool b ) { m_doNotCacheInodes = b; } + + void save( KConfigBase* c, bool saveVolumeDesc = true ); + + static K3bIsoOptions load( KConfigBase* c, bool loadVolumeDesc = true ); + static K3bIsoOptions defaults(); + + private: + // volume descriptor + QString m_volumeID; + QString m_applicationID; + QString m_preparer; + QString m_publisher; + QString m_systemId; + QString m_volumeSetId; + QString m_abstractFile; + QString m_copyrightFile; + QString m_bibliographFile; + + int m_volumeSetSize; + int m_volumeSetNumber; + + bool m_bForceInputCharset; + QString m_inputCharset; + + // mkisofs options ------------------------------------- + bool m_createRockRidge; // -r or -R + bool m_createJoliet; // -J + bool m_createUdf; // -udf + bool m_ISOallowLowercase; // -allow-lowercase + bool m_ISOallowPeriodAtBegin; // -L + bool m_ISOallow31charFilenames; // -I + bool m_ISOomitVersionNumbers; // -N + bool m_ISOomitTrailingPeriod; // -d + bool m_ISOmaxFilenameLength; // -max-iso9660-filenames (forces -N) + bool m_ISOrelaxedFilenames; // -relaxed-filenames + bool m_ISOnoIsoTranslate; // -no-iso-translate + bool m_ISOallowMultiDot; // -allow-multidot + bool m_ISOuntranslatedFilenames; // -U (forces -d, -I, -L, -N, -relaxed-filenames, -allow-lowercase, -allow-multidot, -no-iso-translate) + bool m_followSymbolicLinks; // -f + bool m_createTRANS_TBL; // -T + bool m_hideTRANS_TBL; // -hide-joliet-trans-tbl + + bool m_preserveFilePermissions; // if true -R instead of -r is used + bool m_jolietLong; + + bool m_doNotCacheInodes; + + int m_isoLevel; + + + int m_whiteSpaceTreatment; + QString m_whiteSpaceTreatmentReplaceString; + + bool m_discardSymlinks; + bool m_discardBrokenSymlinks; +}; + +#endif diff --git a/libk3b/projects/datacd/k3bmkisofshandler.cpp b/libk3b/projects/datacd/k3bmkisofshandler.cpp new file mode 100644 index 0000000..a3579ec --- /dev/null +++ b/libk3b/projects/datacd/k3bmkisofshandler.cpp @@ -0,0 +1,150 @@ +/* + * + * $Id: k3bmkisofshandler.cpp 802340 2008-04-29 07:43:07Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bmkisofshandler.h" + +#include +#include +#include + +#include +#include + +#include + + + +class K3bMkisofsHandler::Private +{ +public: + const K3bExternalBin* mkisofsBin; + double firstProgressValue; + bool readError; +}; + + +K3bMkisofsHandler::K3bMkisofsHandler() +{ + d = new Private; + d->mkisofsBin = 0; +} + + +K3bMkisofsHandler::~K3bMkisofsHandler() +{ + delete d; +} + + +bool K3bMkisofsHandler::mkisofsReadError() const +{ + return d->readError; +} + + +const K3bExternalBin* K3bMkisofsHandler::initMkisofs() +{ + d->mkisofsBin = k3bcore->externalBinManager()->binObject( "mkisofs" ); + + if( d->mkisofsBin ) { + if( !d->mkisofsBin->copyright.isEmpty() ) + handleMkisofsInfoMessage( i18n("Using %1 %2 - Copyright (C) %3") + .arg("mkisofs").arg(d->mkisofsBin->version).arg(d->mkisofsBin->copyright), + K3bJob::INFO ); + + d->firstProgressValue = -1; + d->readError = false; + } + else { + kdDebug() << "(K3bMkisofsHandler) could not find mkisofs executable" << endl; + handleMkisofsInfoMessage( i18n("Mkisofs executable not found."), K3bJob::ERROR ); + } + + return d->mkisofsBin; +} + + +void K3bMkisofsHandler::parseMkisofsOutput( const QString& line ) +{ + if( !line.isEmpty() ) { + if( line.startsWith( d->mkisofsBin->path ) ) { + // error or warning + QString errorLine = line.mid( d->mkisofsBin->path.length() + 2 ); + if( errorLine.startsWith( "Input/output error. Cannot read from" ) ) { + handleMkisofsInfoMessage( i18n("Read error from file '%1'").arg( errorLine.mid( 38, errorLine.length()-40 ) ), + K3bJob::ERROR ); + d->readError = true; + } + else if( errorLine.startsWith( "Value too large for defined data type" ) ) { + handleMkisofsInfoMessage( i18n("Used version of mkisofs does not have large file support."), K3bJob::ERROR ); + handleMkisofsInfoMessage( i18n("Files bigger than 2 GB cannot be handled."), K3bJob::ERROR ); + d->readError = true; + } + } + else if( line.contains( "done, estimate" ) ) { + int p = parseMkisofsProgress( line ); + if( p != -1 ) + handleMkisofsProgress( p ); + } + else if( line.contains( "extents written" ) ) { + handleMkisofsProgress( 100 ); + } + else if( line.startsWith( "Incorrectly encoded string" ) ) { + handleMkisofsInfoMessage( i18n("Encountered an incorrectly encoded filename '%1'") + .arg(line.section( QRegExp("[\\(\\)]"), 1, 1 )), K3bJob::ERROR ); + handleMkisofsInfoMessage( i18n("This may be caused by a system update which changed the local character set."), K3bJob::ERROR ); + handleMkisofsInfoMessage( i18n("You may use convmv (http://j3e.de/linux/convmv/) to fix the filename encoding."), K3bJob::ERROR ); + d->readError = true; + } + else if( line.endsWith( "has not an allowable size." ) ) { + handleMkisofsInfoMessage( i18n("The boot image has an invalid size."), K3bJob::ERROR ); + d->readError = true; + } + else if( line.endsWith( "has multiple partitions." ) ) { + handleMkisofsInfoMessage( i18n("The boot image contains multiple partitions.."), K3bJob::ERROR ); + handleMkisofsInfoMessage( i18n("A hard-disk boot image has to contain a single partition."), K3bJob::ERROR ); + d->readError = true; + } + else { + kdDebug() << "(mkisofs) " << line << endl; + } + } +} + + +int K3bMkisofsHandler::parseMkisofsProgress( const QString& line ) +{ + // + // in multisession mode mkisofs' progress does not start at 0 but at (X+Y)/X + // where X is the data already on the cd and Y the data to create + // This is not very dramatic but kind or ugly. + // We just save the first emitted progress value and to some math ;) + // + + QString perStr = line; + perStr.truncate( perStr.find('%') ); + bool ok; + double p = perStr.toDouble( &ok ); + if( !ok ) { + kdDebug() << "(K3bMkisofsHandler) Parsing did not work for " << perStr << endl; + return -1; + } + else { + if( d->firstProgressValue < 0 ) + d->firstProgressValue = p; + + return( (int)::ceil( (p - d->firstProgressValue)*100.0/(100.0 - d->firstProgressValue) ) ); + } +} diff --git a/libk3b/projects/datacd/k3bmkisofshandler.h b/libk3b/projects/datacd/k3bmkisofshandler.h new file mode 100644 index 0000000..32576bc --- /dev/null +++ b/libk3b/projects/datacd/k3bmkisofshandler.h @@ -0,0 +1,74 @@ +/* + * + * $Id: k3bmkisofshandler.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_MKISOfS_HANDLER_H_ +#define _K3B_MKISOfS_HANDLER_H_ + +#include + +class K3bExternalBin; + + +/** + * Derive from this to handle mkisofs. + */ +class K3bMkisofsHandler +{ + public: + K3bMkisofsHandler(); + virtual ~K3bMkisofsHandler(); + + /** + * \return true if there was a read error. + */ + bool mkisofsReadError() const; + + protected: + /** + * Initialize the MkisofsHandler. + * This method emits copyright information and an error message in case mkisofs is not installed + * through handleMkisofsInfoMessage. + * + * \return A mkisofs bin object to be used or 0 if mkisofs is not installed. + */ + const K3bExternalBin* initMkisofs(); + + void parseMkisofsOutput( const QString& line ); + + /** + * Used internally by handleMkisofsOutput. + * May be used in case handleMkisofsOutput is not sufficient. + */ + int parseMkisofsProgress( const QString& line ); + + /** + * Called by handleMkisofsOutput + */ + virtual void handleMkisofsProgress( int ) = 0; + + /** + * Called by handleMkisofsOutput + * + * Uses K3bJob::MessageType + */ + virtual void handleMkisofsInfoMessage( const QString&, int ) = 0; + + private: + class Private; + Private* d; +}; + + +#endif diff --git a/libk3b/projects/datacd/k3bmsinfofetcher.cpp b/libk3b/projects/datacd/k3bmsinfofetcher.cpp new file mode 100644 index 0000000..c30d0ff --- /dev/null +++ b/libk3b/projects/datacd/k3bmsinfofetcher.cpp @@ -0,0 +1,243 @@ +/* + * + * $Id: k3bmsinfofetcher.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bmsinfofetcher.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +K3bMsInfoFetcher::K3bMsInfoFetcher( K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bJob( jh, parent, name ), + m_process(0), + m_device(0), + m_dvd(false) +{ +} + + +K3bMsInfoFetcher::~K3bMsInfoFetcher() +{ + delete m_process; +} + + +void K3bMsInfoFetcher::start() +{ + jobStarted(); + + emit infoMessage( i18n("Searching previous session"), K3bJob::INFO ); + + if( !k3bcore->externalBinManager()->foundBin( "cdrecord" ) ) { + kdDebug() << "(K3bMsInfoFetcher) could not find cdrecord executable" << endl; + emit infoMessage( i18n("Could not find %1 executable.").arg("cdrecord"), K3bJob::ERROR ); + jobFinished(false); + return; + } + + if( m_device == 0 ) { + kdDebug() << "(K3bMsInfoFetcher) internal error: No device set!" << endl; + jobFinished(false); + return; + } + + // + // first we try to determine if it is a dvd. If so we need to + // read the info on our own + // + + connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::NG_DISKINFO, m_device ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotMediaDetectionFinished(K3bDevice::DeviceHandler*)) ); +} + + +void K3bMsInfoFetcher::getMsInfo() +{ + delete m_process; + m_process = new KProcess(); + + const K3bExternalBin* bin = 0; + if( m_dvd ) { + // already handled + } + else { + bin = k3bcore->externalBinManager()->binObject( "cdrecord" ); + + if( !bin ) { + emit infoMessage( i18n("Could not find %1 executable.").arg( m_dvd ? "dvdrecord" : "cdrecord" ), ERROR ); + jobFinished(false); + return; + } + + *m_process << bin->path; + + // add the device (e.g. /dev/sg1) + *m_process << QString("dev=%1").arg( K3b::externalBinDeviceParameter(m_device, bin) ); + + *m_process << "-msinfo"; + + // additional user parameters from config + const QStringList& params = bin->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *m_process << *it; + + kdDebug() << "***** " << bin->name() << " parameters:\n"; + const QValueList& args = m_process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << flush << endl; + emit debuggingOutput( "msinfo command:", s ); + + + // connect( m_process, SIGNAL(receivedStderr(KProcess*, char*, int)), + // this, SLOT(slotCollectOutput(KProcess*, char*, int)) ); + connect( m_process, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotCollectOutput(KProcess*, char*, int)) ); + connect( m_process, SIGNAL(processExited(KProcess*)), + this, SLOT(slotProcessExited()) ); + + m_msInfo = QString::null; + m_collectedOutput = QString::null; + m_canceled = false; + + if( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) { + emit infoMessage( i18n("Could not start %1.").arg(bin->name()), K3bJob::ERROR ); + jobFinished(false); + } + } +} + + +void K3bMsInfoFetcher::slotMediaDetectionFinished( K3bDevice::DeviceHandler* h ) +{ + if( h->success() ) { + m_dvd = h->diskInfo().isDvdMedia(); + } + else { + // for now we just default to cd and go on with the detecting + m_dvd = false; + } + + if( m_dvd ) { + if( h->diskInfo().mediaType() & (K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_RW_OVWR) ) { + // get info from iso filesystem + K3bIso9660 iso( m_device, h->toc().last().firstSector().lba() ); + if( iso.open() ) { + unsigned long long nextSession = iso.primaryDescriptor().volumeSpaceSize; + // pad to closest 32K boundary + nextSession += 15; + nextSession /= 16; + nextSession *= 16; + m_msInfo.sprintf( "16,%llu", nextSession ); + + jobFinished( true ); + } + else { + emit infoMessage( i18n("Could not open Iso9660 filesystem in %1.") + .arg( m_device->vendor() + " " + m_device->description() ), ERROR ); + jobFinished( false ); + } + } + else { + unsigned int lastSessionStart, nextWritableAdress; + if( m_device->getNextWritableAdress( lastSessionStart, nextWritableAdress ) ) { + m_msInfo.sprintf( "%u,%u", lastSessionStart+16, nextWritableAdress ); + jobFinished( true ); + } + else { + emit infoMessage( i18n("Could not determine next writable address."), ERROR ); + jobFinished( false ); + } + } + } + else // call cdrecord + getMsInfo(); +} + + +void K3bMsInfoFetcher::slotProcessExited() +{ + if( m_canceled ) + return; + + kdDebug() << "(K3bMsInfoFetcher) msinfo fetched" << endl; + + // now parse the output + QString firstLine = m_collectedOutput.left( m_collectedOutput.find("\n") ); + QStringList list = QStringList::split( ",", firstLine ); + if( list.count() == 2 ) { + bool ok1, ok2; + m_lastSessionStart = list.first().toInt( &ok1 ); + m_nextSessionStart = list[1].toInt( &ok2 ); + if( ok1 && ok2 ) + m_msInfo = firstLine.stripWhiteSpace(); + else + m_msInfo = QString::null; + } + else { + m_msInfo = QString::null; + } + + kdDebug() << "(K3bMsInfoFetcher) msinfo parsed: " << m_msInfo << endl; + + if( m_msInfo.isEmpty() ) { + emit infoMessage( i18n("Could not retrieve multisession information from disk."), K3bJob::ERROR ); + emit infoMessage( i18n("The disk is either empty or not appendable."), K3bJob::ERROR ); + jobFinished(false); + } + else { + jobFinished(true); + } +} + + +void K3bMsInfoFetcher::slotCollectOutput( KProcess*, char* output, int len ) +{ + emit debuggingOutput( "msinfo", QString::fromLocal8Bit( output, len ) ); + + m_collectedOutput += QString::fromLocal8Bit( output, len ); +} + + +void K3bMsInfoFetcher::cancel() +{ + // FIXME: this does not work if the devicehandler is running + + if( m_process ) + if( m_process->isRunning() ) { + m_canceled = true; + m_process->kill(); + emit canceled(); + jobFinished(false); + } +} + + +#include "k3bmsinfofetcher.moc" diff --git a/libk3b/projects/datacd/k3bmsinfofetcher.h b/libk3b/projects/datacd/k3bmsinfofetcher.h new file mode 100644 index 0000000..593664f --- /dev/null +++ b/libk3b/projects/datacd/k3bmsinfofetcher.h @@ -0,0 +1,64 @@ +/* + * + * $Id: k3bmsinfofetcher.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_MSINFO_FETCHER_H +#define K3B_MSINFO_FETCHER_H + +#include + +namespace K3bDevice { + class Device; + class DeviceHandler; +} +class KProcess; + +class K3bMsInfoFetcher : public K3bJob +{ + Q_OBJECT + + public: + K3bMsInfoFetcher( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bMsInfoFetcher(); + + const QString& msInfo() const { return m_msInfo; } + int lastSessionStart() const { return m_lastSessionStart; } + int nextSessionStart() const { return m_nextSessionStart; } + + public slots: + void start(); + void cancel(); + + void setDevice( K3bDevice::Device* dev ) { m_device = dev; } + + private slots: + void slotProcessExited(); + void slotCollectOutput( KProcess*, char* output, int len ); + void slotMediaDetectionFinished( K3bDevice::DeviceHandler* ); + void getMsInfo(); + + private: + QString m_msInfo; + int m_lastSessionStart; + int m_nextSessionStart; + QString m_collectedOutput; + + KProcess* m_process; + K3bDevice::Device* m_device; + + bool m_canceled; + bool m_dvd; +}; + +#endif diff --git a/libk3b/projects/datacd/k3bsessionimportitem.cpp b/libk3b/projects/datacd/k3bsessionimportitem.cpp new file mode 100644 index 0000000..35f7936 --- /dev/null +++ b/libk3b/projects/datacd/k3bsessionimportitem.cpp @@ -0,0 +1,59 @@ +/* + * + * $Id: k3bsessionimportitem.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bsessionimportitem.h" +#include "k3bfileitem.h" +#include "k3bdiritem.h" + +#include + + +K3bSessionImportItem::K3bSessionImportItem( const K3bIso9660File* isoF, K3bDataDoc* doc, K3bDirItem* dir ) + : K3bDataItem( doc, dir ), + m_replaceItem(0), + m_size( isoF->size() ) + +{ + setK3bName( isoF->name() ); + + // add automagically like a qlistviewitem + if( parent() ) + parent()->addDataItem( this ); +} + + +K3bSessionImportItem::K3bSessionImportItem( const K3bSessionImportItem& item ) + : K3bDataItem( item ), + m_replaceItem( item.m_replaceItem ), + m_size( item.m_size ) +{ +} + + +K3bSessionImportItem::~K3bSessionImportItem() +{ + if( m_replaceItem ) + m_replaceItem->setReplacedItemFromOldSession(0); + + // remove this from parentdir + if( parent() ) + parent()->takeDataItem( this ); +} + + +K3bDataItem* K3bSessionImportItem::copy() const +{ + return new K3bSessionImportItem( *this ); +} diff --git a/libk3b/projects/datacd/k3bsessionimportitem.h b/libk3b/projects/datacd/k3bsessionimportitem.h new file mode 100644 index 0000000..33f8124 --- /dev/null +++ b/libk3b/projects/datacd/k3bsessionimportitem.h @@ -0,0 +1,63 @@ +/* + * + * $Id: k3bsessionimportitem.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_SESSION_IMPORT_ITEM_H_ +#define _K3B_SESSION_IMPORT_ITEM_H_ + + +#include "k3bdataitem.h" + + +class K3bDataDoc; +class K3bFileItem; +class K3bDirItem; +class K3bIso9660File; + + +class K3bSessionImportItem : public K3bDataItem +{ + public: + K3bSessionImportItem( const K3bIso9660File*, K3bDataDoc* doc, K3bDirItem* ); + K3bSessionImportItem( const K3bSessionImportItem& ); + ~K3bSessionImportItem(); + + K3bDataItem* copy() const; + + K3bFileItem* replaceItem() const { return m_replaceItem; } + void setReplaceItem( K3bFileItem* item ) { m_replaceItem = item; } + + bool isFile() const { return false; } + bool isFromOldSession() const { return true; } + + bool isRemoveable() const { return false; } + bool isMoveable() const { return false; } + bool isRenameable() const { return false; } + bool isHideable() const { return false; } + bool writeToCd() const { return false; } + + protected: + // the size of an item from an imported session does not depend + // on the value of followSymlinks + /** + * Normally one does not use this method but K3bDataItem::size() + */ + KIO::filesize_t itemSize( bool ) const { return m_size; } + + private: + K3bFileItem* m_replaceItem; + KIO::filesize_t m_size; +}; + +#endif diff --git a/libk3b/projects/datacd/k3bspecialdataitem.h b/libk3b/projects/datacd/k3bspecialdataitem.h new file mode 100644 index 0000000..05005ed --- /dev/null +++ b/libk3b/projects/datacd/k3bspecialdataitem.h @@ -0,0 +1,76 @@ +/* + * + * $Id: k3bspecialdataitem.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BSPECIALDATAITEM_H +#define K3BSPECIALDATAITEM_H + +#include "k3bdataitem.h" +#include "k3bdiritem.h" + +#include + +/** + * This can be used to create fake items like the boot catalog + * It's mainly a K3bDataItem where everything has to be set manually + */ +class K3bSpecialDataItem : public K3bDataItem +{ + public: + K3bSpecialDataItem( K3bDataDoc* doc, KIO::filesize_t size, K3bDirItem* parent = 0, const QString& k3bName = QString::null ) + : K3bDataItem( doc, parent ), + m_size( size ) + { + setK3bName( k3bName ); + + // add automagically like a qlistviewitem + if( parent ) + parent->addDataItem( this ); + } + + K3bSpecialDataItem( const K3bSpecialDataItem& item ) + : K3bDataItem( item ), + m_mimeType( item.m_mimeType ), + m_size( item.m_size ) { + } + + ~K3bSpecialDataItem() { + // remove this from parentdir + if( parent() ) + parent()->takeDataItem( this ); + } + + K3bDataItem* copy() const { + return new K3bSpecialDataItem( *this ); + } + + void setMimeType( const QString& s ) { m_mimeType = s; } + const QString& mimeType() const { return m_mimeType; } + + bool isSpecialFile() const { return true; } + + protected: + /** + * Normally one does not use this method but K3bDataItem::size() + */ + KIO::filesize_t itemSize( bool ) const { return m_size; } + + private: + QString m_mimeType; + KIO::filesize_t m_size; +}; + +#endif + diff --git a/libk3b/projects/datadvd/Makefile.am b/libk3b/projects/datadvd/Makefile.am new file mode 100644 index 0000000..99ae10c --- /dev/null +++ b/libk3b/projects/datadvd/Makefile.am @@ -0,0 +1,21 @@ +# we need the ../datacd for the uic generated header files +AM_CPPFLAGS= -I$(srcdir)/../../core \ + -I$(srcdir)/../../../libk3bdevice \ + -I$(srcdir)/../../../src \ + -I$(srcdir)/../../tools \ + -I$(srcdir)/../../jobs \ + -I$(srcdir)/../datacd \ + -I$(srcdir)/.. \ + -I../datacd \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libdvd.la + +libdvd_la_SOURCES = k3bdvddoc.cpp \ + k3bdvdjob.cpp \ + k3bdvdbooktypejob.cpp + +include_HEADERS = k3bdvddoc.h \ + k3bdvdjob.h diff --git a/libk3b/projects/datadvd/k3bdvdbooktypejob.cpp b/libk3b/projects/datadvd/k3bdvdbooktypejob.cpp new file mode 100644 index 0000000..f703452 --- /dev/null +++ b/libk3b/projects/datadvd/k3bdvdbooktypejob.cpp @@ -0,0 +1,350 @@ +/* + * + * $Id: k3bdvdbooktypejob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bdvdbooktypejob.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +class K3bDvdBooktypeJob::Private +{ +public: + Private() + : device(0), + process(0), + dvdBooktypeBin(0), + running(false), + forceNoEject(false) { + } + + K3bDevice::Device* device; + K3bProcess* process; + const K3bExternalBin* dvdBooktypeBin; + + bool success; + bool canceled; + bool running; + + bool forceNoEject; + + int foundMediaType; +}; + + +K3bDvdBooktypeJob::K3bDvdBooktypeJob( K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bJob( jh, parent, name ), + m_action(0) +{ + d = new Private; +} + + +K3bDvdBooktypeJob::~K3bDvdBooktypeJob() +{ + delete d->process; + delete d; +} + + +void K3bDvdBooktypeJob::setForceNoEject( bool b ) +{ + d->forceNoEject = b; +} + + +QString K3bDvdBooktypeJob::jobDescription() const +{ + return i18n("Changing DVD Booktype"); // Changing DVD±R(W) Booktype +} + + +QString K3bDvdBooktypeJob::jobDetails() const +{ + return QString::null; +} + + +void K3bDvdBooktypeJob::start() +{ + d->canceled = false; + d->running = true; + + jobStarted(); + + if( !d->device ) { + emit infoMessage( i18n("No device set"), ERROR ); + jobFinished(false); + d->running = false; + return; + } + + // + // In case we want to change the writers default we do not need to wait for a media + // + if( m_action == SET_MEDIA_DVD_ROM || + m_action == SET_MEDIA_DVD_R_W ) { + emit newSubTask( i18n("Waiting for media") ); + if( waitForMedia( d->device, + K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE|K3bDevice::STATE_EMPTY, + K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_PLUS_R, + i18n("Please insert an empty DVD+R or a DVD+RW medium into drive

%1 %2 (%3).") + .arg(d->device->vendor()).arg(d->device->description()).arg(d->device->devicename()) ) == -1 ) { + emit canceled(); + jobFinished(false); + d->running = false; + return; + } + + emit infoMessage( i18n("Checking media..."), INFO ); + emit newTask( i18n("Checking media") ); + + connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::NG_DISKINFO, d->device ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotDeviceHandlerFinished(K3bDevice::DeviceHandler*)) ); + } + else { + // change writer defaults + startBooktypeChange(); + } +} + + +void K3bDvdBooktypeJob::start( K3bDevice::DeviceHandler* dh ) +{ + d->canceled = false; + d->running = true; + + jobStarted(); + + slotDeviceHandlerFinished( dh ); +} + + +void K3bDvdBooktypeJob::cancel() +{ + if( d->running ) { + d->canceled = true; + if( d->process ) + d->process->kill(); + } + else { + kdDebug() << "(K3bDvdBooktypeJob) not running." << endl; + } +} + + +void K3bDvdBooktypeJob::setDevice( K3bDevice::Device* dev ) +{ + d->device = dev; +} + + +void K3bDvdBooktypeJob::slotStderrLine( const QString& line ) +{ + emit debuggingOutput( "dvd+rw-booktype", line ); + // FIXME +} + + +void K3bDvdBooktypeJob::slotProcessFinished( KProcess* p ) +{ + if( d->canceled ) { + emit canceled(); + d->success = false; + } + else if( p->normalExit() ) { + if( p->exitStatus() == 0 ) { + emit infoMessage( i18n("Booktype successfully changed"), K3bJob::SUCCESS ); + d->success = true; + } + else { + emit infoMessage( i18n("%1 returned an unknown error (code %2).").arg(d->dvdBooktypeBin->name()).arg(p->exitStatus()), + K3bJob::ERROR ); + emit infoMessage( i18n("Please send me an email with the last output."), K3bJob::ERROR ); + + d->success = false; + } + } + else { + emit infoMessage( i18n("%1 did not exit cleanly.").arg(d->dvdBooktypeBin->name()), + ERROR ); + d->success = false; + } + + // + // No need to eject the media if we changed the writer's default + // + if( m_action == SET_MEDIA_DVD_ROM || + m_action == SET_MEDIA_DVD_R_W ) { + + if( d->forceNoEject || + !k3bcore->globalSettings()->ejectMedia() ) { + d->running = false; + jobFinished(d->success); + } + else { + emit infoMessage( i18n("Ejecting DVD..."), INFO ); + connect( K3bDevice::eject( d->device ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotEjectingFinished(K3bDevice::DeviceHandler*)) ); + } + } + else { + d->running = false; + jobFinished(d->success); + } +} + + +void K3bDvdBooktypeJob::slotEjectingFinished( K3bDevice::DeviceHandler* dh ) +{ + if( !dh->success() ) + emit infoMessage( i18n("Unable to eject media."), ERROR ); + + d->running = false; + jobFinished(d->success); +} + + +void K3bDvdBooktypeJob::slotDeviceHandlerFinished( K3bDevice::DeviceHandler* dh ) +{ + if( d->canceled ) { + emit canceled(); + d->running = false; + jobFinished(false); + } + + if( dh->success() ) { + + d->foundMediaType = dh->diskInfo().mediaType(); + if( d->foundMediaType == K3bDevice::MEDIA_DVD_PLUS_R ) { + // the media needs to be empty + if( dh->diskInfo().empty() ) + startBooktypeChange(); + else { + emit infoMessage( i18n("Cannot change booktype on non-empty DVD+R media."), ERROR ); + jobFinished(false); + } + } + else if( d->foundMediaType == K3bDevice::MEDIA_DVD_PLUS_RW ) { + startBooktypeChange(); + } + else { + emit infoMessage( i18n("No DVD+R(W) media found."), ERROR ); + jobFinished(false); + } + } + else { + emit infoMessage( i18n("Unable to determine media state."), ERROR ); + d->running = false; + jobFinished(false); + } +} + + +void K3bDvdBooktypeJob::startBooktypeChange() +{ + delete d->process; + d->process = new K3bProcess(); + d->process->setRunPrivileged(true); + d->process->setSuppressEmptyLines(true); + connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotStderrLine(const QString&)) ); + connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessFinished(KProcess*)) ); + + d->dvdBooktypeBin = k3bcore->externalBinManager()->binObject( "dvd+rw-booktype" ); + if( !d->dvdBooktypeBin ) { + emit infoMessage( i18n("Could not find %1 executable.").arg("dvd+rw-booktype"), ERROR ); + d->running = false; + jobFinished(false); + return; + } + + *d->process << d->dvdBooktypeBin; + + switch( m_action ) { + case SET_MEDIA_DVD_ROM: + *d->process << "-dvd-rom-spec" + << "-media"; + break; + case SET_MEDIA_DVD_R_W: + if( d->foundMediaType == K3bDevice::MEDIA_DVD_PLUS_RW ) + *d->process << "-dvd+rw-spec"; + else + *d->process << "-dvd+r-spec"; + *d->process << "-media"; + break; + case SET_UNIT_DVD_ROM_ON_NEW_DVD_R: + *d->process << "-dvd-rom-spec" + << "-unit+r"; + break; + case SET_UNIT_DVD_ROM_ON_NEW_DVD_RW: + *d->process << "-dvd-rom-spec" + << "-unit+rw"; + break; + case SET_UNIT_DVD_R_ON_NEW_DVD_R: + *d->process << "-dvd+r-spec" + << "-unit+r"; + break; + case SET_UNIT_DVD_RW_ON_NEW_DVD_RW: + *d->process << "-dvd+rw-spec" + << "-unit+rw"; + break; + } + + *d->process << d->device->blockDeviceName(); + + kdDebug() << "***** dvd+rw-booktype parameters:\n"; + const QValueList& args = d->process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << endl << flush; + emit debuggingOutput( "dvd+rw-booktype command:", s ); + + + if( !d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) { + // something went wrong when starting the program + // it "should" be the executable + emit infoMessage( i18n("Could not start %1.").arg(d->dvdBooktypeBin->name()), K3bJob::ERROR ); + d->running = false; + jobFinished(false); + } + else { + emit newTask( i18n("Changing Booktype") ); + } +} + +#include "k3bdvdbooktypejob.moc" diff --git a/libk3b/projects/datadvd/k3bdvdbooktypejob.h b/libk3b/projects/datadvd/k3bdvdbooktypejob.h new file mode 100644 index 0000000..b9e7e4b --- /dev/null +++ b/libk3b/projects/datadvd/k3bdvdbooktypejob.h @@ -0,0 +1,99 @@ +/* + * + * $Id: k3bdvdbooktypejob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_DVD_BOOKTYPE_JOB_H_ +#define _K3B_DVD_BOOKTYPE_JOB_H_ + + +#include + + +class KProcess; +namespace K3bDevice { + class Device; + class DeviceHandler; +} + + +/** + * This job can change the compatibility bit of DVD+R(W) media + * with supported dvd writers. + */ +class K3bDvdBooktypeJob : public K3bJob +{ + Q_OBJECT + + public: + K3bDvdBooktypeJob( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bDvdBooktypeJob(); + + QString jobDescription() const; + QString jobDetails() const; + + /** + * @list SET_MEDIA_DVD_ROM Change media identification on current media to DVD-ROM. + * @list SET_MEDIA_DVD_R_W Change media identification on current media to DVD+R or DVD+RW. + * @list SET_UNIT_DVD_ROM_ON_NEW_DVD_R Set the drive to write DVD-ROM specification on future written DVD+R discs. + * @list SET_UNIT_DVD_ROM_ON_NEW_DVD_RW Set the drive to write DVD-ROM specification on future written DVD+RW discs. + * @list SET_UNIT_DVD_R_ON_NEW_DVD_R Set the drive to write DVD+R specification on future written DVD+R discs. + * @list SET_UNIT_DVD_RW_ON_NEW_DVD_RW Set the drive to write DVD+RW specification on future written DVD+RW discs. + */ + enum Action { + SET_MEDIA_DVD_ROM, + SET_MEDIA_DVD_R_W, + SET_UNIT_DVD_ROM_ON_NEW_DVD_R, + SET_UNIT_DVD_ROM_ON_NEW_DVD_RW, + SET_UNIT_DVD_R_ON_NEW_DVD_R, + SET_UNIT_DVD_RW_ON_NEW_DVD_RW + }; + + public slots: + void start(); + + /** + * The devicehandler needs to have a valid NgDiskInfo + * Use this to prevent the job from searching a media. + */ + void start( K3bDevice::DeviceHandler* ); + + void cancel(); + + void setDevice( K3bDevice::Device* ); + + void setAction( int a ) { m_action = a; } + + /** + * If set true the job ignores the global K3b setting + * and does not eject the CD-RW after finishing + */ + void setForceNoEject( bool ); + + private slots: + void slotStderrLine( const QString& ); + void slotProcessFinished( KProcess* ); + void slotDeviceHandlerFinished( K3bDevice::DeviceHandler* ); + void slotEjectingFinished( K3bDevice::DeviceHandler* ); + + private: + void startBooktypeChange(); + + int m_action; + + class Private; + Private* d; +}; + + +#endif diff --git a/libk3b/projects/datadvd/k3bdvddoc.cpp b/libk3b/projects/datadvd/k3bdvddoc.cpp new file mode 100644 index 0000000..4ab8b9f --- /dev/null +++ b/libk3b/projects/datadvd/k3bdvddoc.cpp @@ -0,0 +1,39 @@ +/* + * + * $Id: k3bdvddoc.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bdvddoc.h" +#include "k3bdvdjob.h" + +#include + +#include + + +K3bDvdDoc::K3bDvdDoc( QObject* parent ) + : K3bDataDoc( parent ) +{ +} + +K3bDvdDoc::~K3bDvdDoc() +{ +} + +K3bBurnJob* K3bDvdDoc::newBurnJob( K3bJobHandler* hdl, QObject* parent ) +{ + return new K3bDvdJob( this, hdl, parent ); +} + +//#include "k3bdvddoc.moc" diff --git a/libk3b/projects/datadvd/k3bdvddoc.h b/libk3b/projects/datadvd/k3bdvddoc.h new file mode 100644 index 0000000..03b5c3d --- /dev/null +++ b/libk3b/projects/datadvd/k3bdvddoc.h @@ -0,0 +1,37 @@ +/* + * + * $Id: k3bdvddoc.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_DVDDOC_H_ +#define _K3B_DVDDOC_H_ + +#include +#include "k3b_export.h" +class KConfig; + +class LIBK3B_EXPORT K3bDvdDoc : public K3bDataDoc +{ + public: + K3bDvdDoc( QObject* parent = 0 ); + virtual ~K3bDvdDoc(); + + virtual int type() const { return DVD; } + + virtual K3bBurnJob* newBurnJob( K3bJobHandler* hdl, QObject* parent = 0 ); + + protected: + virtual QString typeString() const { return "dvd"; } +}; + +#endif diff --git a/libk3b/projects/datadvd/k3bdvdjob.cpp b/libk3b/projects/datadvd/k3bdvdjob.cpp new file mode 100644 index 0000000..3cd1521 --- /dev/null +++ b/libk3b/projects/datadvd/k3bdvdjob.cpp @@ -0,0 +1,344 @@ +/* + * + * $Id: k3bdvdjob.cpp 690187 2007-07-20 09:18:03Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bdvdjob.h" +#include "k3bdvddoc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +class K3bDvdJob::Private +{ +public: +}; + + +K3bDvdJob::K3bDvdJob( K3bDataDoc* doc, K3bJobHandler* hdl, QObject* parent ) + : K3bDataJob( doc, hdl, parent ), + m_doc( doc ) +{ + d = new Private(); +} + + +K3bDvdJob::~K3bDvdJob() +{ + delete d; +} + + +void K3bDvdJob::prepareData() +{ +} + + +bool K3bDvdJob::prepareWriterJob() +{ + K3bGrowisofsWriter* writer = new K3bGrowisofsWriter( m_doc->burner(), this, this ); + + // these do only make sense with DVD-R(W) + writer->setSimulate( m_doc->dummy() ); + writer->setBurnSpeed( m_doc->speed() ); + + // Andy said incremental sequential is the default mode and it seems uses have more problems with DAO anyway + // BUT: I also had a report that incremental sequential produced unreadable media! + if( m_doc->writingMode() == K3b::DAO ) +// || ( m_doc->writingMode() == K3b::WRITING_MODE_AUTO && +// usedMultiSessionMode() == K3bDataDoc::NONE ) ) + writer->setWritingMode( K3b::DAO ); + + writer->setMultiSession( usedMultiSessionMode() == K3bDataDoc::CONTINUE || + usedMultiSessionMode() == K3bDataDoc::FINISH ); + + writer->setCloseDvd( usedMultiSessionMode() == K3bDataDoc::NONE || + usedMultiSessionMode() == K3bDataDoc::FINISH ); + + writer->setImageToWrite( QString::null ); // read from stdin + writer->setTrackSize( m_isoImager->size() ); + + if( usedMultiSessionMode() != K3bDataDoc::NONE ) { + // + // growisofs wants a valid -C parameter for multisession, so we get it from the + // K3bMsInfoFetcher (see K3bDataJob::slotMsInfoFetched) + // + writer->setMultiSessionInfo( m_msInfoFetcher->msInfo() ); + } + + setWriterJob( writer ); + + return true; +} + + +void K3bDvdJob::determineMultiSessionMode() +{ + int m = requestMedia( K3bDevice::STATE_INCOMPLETE|K3bDevice::STATE_EMPTY ); + + if( m < 0 ) { + cancel(); + } + else { + connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::NG_DISKINFO, m_doc->burner() ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotDetermineMultiSessionMode(K3bDevice::DeviceHandler*)) ); + } +} + + +K3bDataDoc::MultiSessionMode K3bDvdJob::getMultiSessionMode( const K3bDevice::DiskInfo& info ) +{ + K3bDataDoc::MultiSessionMode mode = K3bDataDoc::NONE; + + if( info.mediaType() & (K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_RW_OVWR) ) { + // + // we need to handle DVD+RW and DVD-RW overwrite media differently since remainingSize() is not valid + // in both cases + // Since one never closes a DVD+RW we only differ between CONTINUE and START + // + + // try to check the filesystem size + K3bIso9660 iso( m_doc->burner() ); + if( iso.open() && info.capacity() - iso.primaryDescriptor().volumeSpaceSize >= m_doc->burningLength() ) { + mode = K3bDataDoc::CONTINUE; + } + else { + mode = K3bDataDoc::START; + } + } + else if( info.appendable() ) { + // + // 3 cases: + // 1. the project does not fit -> no multisession (resulting in asking for another media above) + // 2. the project does fit and fills up the CD (No new sessions after the 4GB boundary) -> finish multisession + // 3. the project does fit and does not fill up the CD -> continue multisession + // + if( m_doc->size() > info.remainingSize().mode1Bytes() && !m_doc->sessionImported() ) + mode = K3bDataDoc::NONE; + else if( info.size() + m_doc->burningLength() + 11400 /* used size + project size + session gap */ > 2097152 /* 4 GB */ ) + mode = K3bDataDoc::FINISH; + else + mode = K3bDataDoc::CONTINUE; + } + else { + // + // We only close the DVD if the project fills it beyond the 4GB boundary + // + if( info.size() + m_doc->burningLength() + 11400 /* used size + project size + session gap */ > 2097152 /* 4 GB */ || + m_doc->writingMode() == K3b::DAO ) + mode = K3bDataDoc::NONE; + else + mode = K3bDataDoc::START; + } + + return mode; +} + + +int K3bDvdJob::requestMedia( int state ) +{ + int mt = 0; + if( m_doc->writingMode() == K3b::WRITING_MODE_RES_OVWR ) // we treat DVD+R(W) as restricted overwrite media + mt = K3bDevice::MEDIA_DVD_RW_OVWR|K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_PLUS_R; + else + mt = K3bDevice::MEDIA_WRITABLE_DVD; + + // double layer media + // in case overburn is enabled we allow some made up max size + // before we force a DL medium + if( m_doc->size() > 4700372992LL ) { + if( !k3bcore->globalSettings()->overburn() || + m_doc->size() > 4900000000LL ) { + mt = K3bDevice::MEDIA_WRITABLE_DVD_DL; + } + } + + return waitForMedia( m_doc->burner(), + state, + mt ); +} + + +bool K3bDvdJob::waitForMedium() +{ + emit infoMessage( i18n("Waiting for media") + "...", INFO ); + + int foundMedium = requestMedia( usedMultiSessionMode() == K3bDataDoc::CONTINUE || + usedMultiSessionMode() == K3bDataDoc::FINISH ? + K3bDevice::STATE_INCOMPLETE : + K3bDevice::STATE_EMPTY ); + + if( foundMedium < 0 || hasBeenCanceled() ) { + return false; + } + + if( foundMedium == 0 ) { + emit infoMessage( i18n("Forced by user. Growisofs will be called without further tests."), INFO ); + } + + else { + // ------------------------------- + // DVD Plus + // ------------------------------- + if( foundMedium & K3bDevice::MEDIA_DVD_PLUS_ALL ) { + if( m_doc->dummy() ) { + if( !questionYesNo( i18n("K3b does not support simulation with DVD+R(W) media. " + "Do you really want to continue? The media will be written " + "for real."), + i18n("No Simulation with DVD+R(W)") ) ) { + return false; + } + + m_doc->setDummy( false ); + emit newTask( i18n("Writing") ); + } + + if( m_doc->writingMode() != K3b::WRITING_MODE_AUTO && m_doc->writingMode() != K3b::WRITING_MODE_RES_OVWR ) + emit infoMessage( i18n("Writing mode ignored when writing DVD+R(W) media."), INFO ); + + if( foundMedium & K3bDevice::MEDIA_DVD_PLUS_RW ) { + if( usedMultiSessionMode() == K3bDataDoc::NONE || + usedMultiSessionMode() == K3bDataDoc::START ) + emit infoMessage( i18n("Writing DVD+RW."), INFO ); + else + emit infoMessage( i18n("Growing ISO9660 filesystem on DVD+RW."), INFO ); + } + else if( foundMedium & K3bDevice::MEDIA_DVD_PLUS_R_DL ) + emit infoMessage( i18n("Writing Double Layer DVD+R."), INFO ); + else + emit infoMessage( i18n("Writing DVD+R."), INFO ); + } + + // ------------------------------- + // DVD Minus + // ------------------------------- + else { + if( m_doc->dummy() && !m_doc->burner()->dvdMinusTestwrite() ) { + if( !questionYesNo( i18n("Your writer (%1 %2) does not support simulation with DVD-R(W) media. " + "Do you really want to continue? The media will be written " + "for real.") + .arg(m_doc->burner()->vendor()) + .arg(m_doc->burner()->description()), + i18n("No Simulation with DVD-R(W)") ) ) { + return false; + } + + m_doc->setDummy( false ); + } + + // RESTRICTED OVERWRITE + // -------------------- + if( foundMedium & K3bDevice::MEDIA_DVD_RW_OVWR ) { + if( usedMultiSessionMode() == K3bDataDoc::NONE || + usedMultiSessionMode() == K3bDataDoc::START ) + emit infoMessage( i18n("Writing DVD-RW in restricted overwrite mode."), INFO ); + else + emit infoMessage( i18n("Growing ISO9660 filesystem on DVD-RW in restricted overwrite mode."), INFO ); + } + + // NORMAL + // ------ + else { + + // FIXME: DVD-R DL jump and stuff + + if( m_doc->writingMode() == K3b::DAO ) + // || ( m_doc->writingMode() == K3b::WRITING_MODE_AUTO && +// usedMultiSessionMode() == K3bDataDoc::NONE ) ) + emit infoMessage( i18n("Writing %1 in DAO mode.").arg( K3bDevice::mediaTypeString(foundMedium, true) ), INFO ); + + else { + // check if the writer supports writing sequential and thus multisession (on -1 the burner cannot handle + // features and we simply ignore it and hope for the best) + if( m_doc->burner()->featureCurrent( K3bDevice::FEATURE_INCREMENTAL_STREAMING_WRITABLE ) == 0 ) { + if( !questionYesNo( i18n("Your writer (%1 %2) does not support Incremental Streaming with %3 " + "media. Multisession will not be possible. Continue anyway?") + .arg(m_doc->burner()->vendor()) + .arg(m_doc->burner()->description()) + .arg( K3bDevice::mediaTypeString(foundMedium, true) ), + i18n("No Incremental Streaming") ) ) { + return false; + } + else { + emit infoMessage( i18n("Writing %1 in DAO mode.").arg( K3bDevice::mediaTypeString(foundMedium, true) ), INFO ); + } + } + else { + if( !(foundMedium & (K3bDevice::MEDIA_DVD_RW|K3bDevice::MEDIA_DVD_RW_OVWR|K3bDevice::MEDIA_DVD_RW_SEQ)) && + m_doc->writingMode() == K3b::WRITING_MODE_RES_OVWR ) + emit infoMessage( i18n("Restricted Overwrite is not possible with DVD-R media."), INFO ); + + emit infoMessage( i18n("Writing %1 in incremental mode.").arg( K3bDevice::mediaTypeString(foundMedium, true) ), INFO ); + } + } + } + } + } + + return true; +} + + +QString K3bDvdJob::jobDescription() const +{ + if( m_doc->onlyCreateImages() ) { + return i18n("Creating Data Image File"); + } + else if( m_doc->multiSessionMode() == K3bDataDoc::NONE || + m_doc->multiSessionMode() == K3bDataDoc::AUTO ) { + return i18n("Writing Data DVD") + + ( m_doc->isoOptions().volumeID().isEmpty() + ? QString::null + : QString( " (%1)" ).arg(m_doc->isoOptions().volumeID()) ); + } + else { + return i18n("Writing Multisession DVD") + + ( m_doc->isoOptions().volumeID().isEmpty() + ? QString::null + : QString( " (%1)" ).arg(m_doc->isoOptions().volumeID()) ); + } +} + + +QString K3bDvdJob::jobDetails() const +{ + if( m_doc->copies() > 1 && + !m_doc->dummy() && + !(m_doc->multiSessionMode() == K3bDataDoc::CONTINUE || + m_doc->multiSessionMode() == K3bDataDoc::FINISH) ) + return i18n("ISO9660 Filesystem (Size: %1) - %n copy", + "ISO9660 Filesystem (Size: %1) - %n copies", + m_doc->copies()) + .arg(KIO::convertSize( m_doc->size() )); + else + return i18n("ISO9660 Filesystem (Size: %1)") + .arg(KIO::convertSize( m_doc->size() )); +} + +#include "k3bdvdjob.moc" diff --git a/libk3b/projects/datadvd/k3bdvdjob.h b/libk3b/projects/datadvd/k3bdvdjob.h new file mode 100644 index 0000000..381bc1d --- /dev/null +++ b/libk3b/projects/datadvd/k3bdvdjob.h @@ -0,0 +1,57 @@ +/* + * + * $Id: k3bdvdjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_DVD_JOB_H_ +#define _K3B_DVD_JOB_H_ + +#include + +#include + +class K3bDataDoc; +class K3bGrowisofsWriter; + + +class K3bDvdJob : public K3bDataJob +{ + Q_OBJECT + + public: + /** + * To be more flexible we allow writing of any data doc + */ + K3bDvdJob( K3bDataDoc*, K3bJobHandler*, QObject* parent = 0 ); + virtual ~K3bDvdJob(); + + virtual QString jobDescription() const; + virtual QString jobDetails() const; + + protected: + void prepareData(); + virtual bool prepareWriterJob(); + void determineMultiSessionMode(); + K3bDataDoc::MultiSessionMode getMultiSessionMode( const K3bDevice::DiskInfo& ); + bool waitForMedium(); + int requestMedia( int state ); + + private: + K3bDataDoc* m_doc; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/datadvd/k3bdvdview.cpp b/libk3b/projects/datadvd/k3bdvdview.cpp new file mode 100644 index 0000000..512ec4b --- /dev/null +++ b/libk3b/projects/datadvd/k3bdvdview.cpp @@ -0,0 +1,48 @@ +/* + * + * $Id: k3bdvdview.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bdvdview.h" +#include "k3bdvddoc.h" +#include "k3bdvdburndialog.h" +#include +#include + +#include + + +K3bDvdView::K3bDvdView( K3bDvdDoc* doc, QWidget *parent, const char *name ) + : K3bDataView( doc, parent, name ) +{ + m_doc = doc; + + fillStatusDisplay()->showDvdSizes(true); + + m_dataFileView->setNoItemText( i18n("Use drag'n'drop to add files and directories to the project.\n" + "To remove or rename files use the context menu.\n" + "After that press the burn button to write the DVD.") ); +} + + +K3bDvdView::~K3bDvdView() +{ +} + + +K3bProjectBurnDialog* K3bDvdView::newBurnDialog( QWidget* parent, const char* name ) +{ + return new K3bDvdBurnDialog( m_doc, parent, name, true ); +} + +#include "k3bdvdview.moc" diff --git a/libk3b/projects/datadvd/k3bdvdview.h b/libk3b/projects/datadvd/k3bdvdview.h new file mode 100644 index 0000000..d9f30f3 --- /dev/null +++ b/libk3b/projects/datadvd/k3bdvdview.h @@ -0,0 +1,40 @@ +/* + * + * $Id: k3bdvdview.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_DVDVIEW_H_ +#define _K3B_DVDVIEW_H_ + +#include + +class K3bDvdDoc; + + +class K3bDvdView : public K3bDataView +{ + Q_OBJECT + + public: + K3bDvdView( K3bDvdDoc* doc, QWidget *parent = 0, const char *name = 0 ); + ~K3bDvdView(); + + protected: + virtual K3bProjectBurnDialog* newBurnDialog( QWidget* parent = 0, const char* name = 0 ); + + private: + K3bDvdDoc* m_doc; +}; + +#endif diff --git a/libk3b/projects/k3babstractwriter.cpp b/libk3b/projects/k3babstractwriter.cpp new file mode 100644 index 0000000..df22bc3 --- /dev/null +++ b/libk3b/projects/k3babstractwriter.cpp @@ -0,0 +1,96 @@ +/* + * + * $Id: k3babstractwriter.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3babstractwriter.h" + +#include +#include +#include +#include + +#include +#include + + + +K3bAbstractWriter::K3bAbstractWriter( K3bDevice::Device* dev, K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bJob( jh, parent, name ), + m_burnDevice(dev), + m_burnSpeed(1), + m_simulate(false), + m_sourceUnreadable(false) +{ +} + + +K3bAbstractWriter::~K3bAbstractWriter() +{ +} + + +K3bDevice::Device* K3bAbstractWriter::burnDevice() +{ + if( m_burnDevice ) + return m_burnDevice; + else + return k3bcore->deviceManager()->burningDevices().getFirst(); +} + + +void K3bAbstractWriter::cancel() +{ + if( burnDevice() ) { + // we need to unlock the writer because cdrecord locked it while writing + emit infoMessage( i18n("Unlocking drive..."), INFO ); + connect( K3bDevice::unblock( burnDevice() ), SIGNAL(finished(bool)), + this, SLOT(slotUnblockWhileCancellationFinished(bool)) ); + } + else { + emit canceled(); + jobFinished(false); + } +} + + +void K3bAbstractWriter::slotUnblockWhileCancellationFinished( bool success ) +{ + if( !success ) + emit infoMessage( i18n("Could not unlock CD drive."), K3bJob::ERROR ); // FIXME: simply "drive", not "CD drive" + + if( k3bcore->globalSettings()->ejectMedia() ) { + emit newSubTask( i18n("Ejecting CD") ); // FIXME: "media" instead of "CD" + connect( K3bDevice::eject( burnDevice() ), SIGNAL(finished(bool)), + this, SLOT(slotEjectWhileCancellationFinished(bool)) ); + } + else { + emit canceled(); + jobFinished( false ); + } +} + + +void K3bAbstractWriter::slotEjectWhileCancellationFinished( bool success ) +{ + if( !success ) { + emit infoMessage( i18n("Unable to eject media."), K3bJob::ERROR ); + } + + emit canceled(); + jobFinished( false ); +} + + +#include "k3babstractwriter.moc" diff --git a/libk3b/projects/k3babstractwriter.h b/libk3b/projects/k3babstractwriter.h new file mode 100644 index 0000000..3f91ee3 --- /dev/null +++ b/libk3b/projects/k3babstractwriter.h @@ -0,0 +1,92 @@ +/* + * + * $Id: k3babstractwriter.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3B_ABSTRACT_WRITER_H +#define K3B_ABSTRACT_WRITER_H + + +#include "k3bjob.h" + +#include + +class K3bDevice::Device; +class K3bJobHandler; + + +class K3bAbstractWriter : public K3bJob +{ + Q_OBJECT + + public: + virtual ~K3bAbstractWriter(); + + K3bDevice::Device* burnDevice(); + int burnSpeed() const { return m_burnSpeed; } + bool simulate() const { return m_simulate; } + + /** + * This can be used to setup direct streaming between two processes + * for example the cdrecordwriter returnes the stdin fd which can be + * connected to the stdout fd of mkisofs in the isoimager + */ + virtual int fd() const { return -1; } + virtual bool closeFd() { return false; } + + public slots: + /** + * If the burnDevice is set this will try to unlock the drive and + * eject the disk if K3b is configured to do so. + * Will also emit canceled and finished signals. + * may be called by subclasses. + */ + void cancel(); + + void setBurnDevice( K3bDevice::Device* dev ) { m_burnDevice = dev; } + void setBurnSpeed( int s ) { m_burnSpeed = s; } + void setSimulate( bool b ) { m_simulate = b; } + + /** + * Used to inform the writer that the source (especially useful when reading from + * another cd/dvd media) could not be read. + * + * Basically it should be used to make sure no "write an email" message is thrown. + */ + void setSourceUnreadable( bool b = true ) { m_sourceUnreadable = b; } + + signals: + void buffer( int ); + void deviceBuffer( int ); + void writeSpeed( int, int ); + + protected: + K3bAbstractWriter( K3bDevice::Device* dev, K3bJobHandler* hdl, + QObject* parent = 0, const char* name = 0 ); + + bool wasSourceUnreadable() const { return m_sourceUnreadable; } + + protected slots: + void slotUnblockWhileCancellationFinished( bool success ); + void slotEjectWhileCancellationFinished( bool success ); + + private: + K3bDevice::Device* m_burnDevice; + int m_burnSpeed; + bool m_simulate; + bool m_sourceUnreadable; +}; + + +#endif diff --git a/libk3b/projects/k3bcdrdaowriter.cpp b/libk3b/projects/k3bcdrdaowriter.cpp new file mode 100644 index 0000000..c49cb4b --- /dev/null +++ b/libk3b/projects/k3bcdrdaowriter.cpp @@ -0,0 +1,1101 @@ +/* + * + * $Id: k3bcdrdaowriter.cpp 654649 2007-04-16 17:55:50Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * Klaus-Dieter Krannich + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bcdrdaowriter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + + + +#define PGSMSG_MIN PGSMSG_RCD_ANALYZING +#define PGSMSG_RCD_ANALYZING 1 +#define PGSMSG_RCD_EXTRACTING 2 +#define PGSMSG_WCD_LEADIN 3 +#define PGSMSG_WCD_DATA 4 +#define PGSMSG_WCD_LEADOUT 5 +#define PGSMSG_BLK 6 +#define PGSMSG_MAX PGSMSG_BLK + +struct ProgressMsg { + int status; // see PGSMSG_* constants + int totalTracks; // total number of tracks + int track; // actually written track + int trackProgress; // progress for current track 0..1000 + int totalProgress; // total writing progress 0..1000 + int bufferFillRate; // buffer fill rate 0..100 +}; + +#define PSGMSG_MINSIZE 24 + +struct ProgressMsg2 { + int status; // see PGSMSG_* constants + int totalTracks; // total number of tracks + int track; // actually written track + int trackProgress; // progress for current track 0..1000 + int totalProgress; // total writing progress 0..1000 + int bufferFillRate; // buffer fill rate 0..100 + int writerFillRate; // device write buffer fill rate 0..100 +}; + + +inline bool operator<( const ProgressMsg2& m1, const ProgressMsg2& m2 ) +{ + return m1.track < m2.track + || ( m1.track == m2.track + && m1.trackProgress < m2.trackProgress ) + || m1.totalProgress < m2.totalProgress; +} + + +inline bool operator==( const ProgressMsg2& m1, const ProgressMsg2& m2 ) +{ + return m1.status == m2.status + && m1.track == m2.track + && m1.totalTracks == m2.totalTracks + && m1.trackProgress == m2.trackProgress + && m1.totalProgress == m2.totalProgress + && m1.bufferFillRate == m2.bufferFillRate; +} + +inline bool operator!=( const ProgressMsg2& m1, const ProgressMsg2& m2 ) +{ + return !( m1 == m2 ); +} + + + +class K3bCdrdaoWriter::Private +{ +public: + Private() { + } + + K3bThroughputEstimator* speedEst; + + int usedSpeed; + + ProgressMsg2 oldMsg; + ProgressMsg2 newMsg; + + unsigned int progressMsgSize; +}; + + +K3bCdrdaoWriter::K3bCdrdaoWriter( K3bDevice::Device* dev, K3bJobHandler* hdl, + QObject* parent, const char* name ) + : K3bAbstractWriter( dev, hdl, parent, name ), + m_command(WRITE), + m_blankMode(MINIMAL), + m_sourceDevice(0), + m_readRaw(false), + m_multi(false), + m_force(false), + m_onTheFly(false), + m_fastToc(false), + m_readSubchan(None), + m_taoSource(false), + m_taoSourceAdjust(-1), + m_paranoiaMode(-1), + m_session(-1), + m_process(0), + m_comSock(0), + m_currentTrack(0), + m_forceNoEject(false) +{ + d = new Private(); + d->speedEst = new K3bThroughputEstimator( this ); + connect( d->speedEst, SIGNAL(throughput(int)), + this, SLOT(slotThroughput(int)) ); + + m_eject = k3bcore->globalSettings()->ejectMedia(); + + ::memset( &d->oldMsg, 0, sizeof(ProgressMsg2) ); + ::memset( &d->newMsg, 0, sizeof(ProgressMsg2) ); + + if( socketpair(AF_UNIX,SOCK_STREAM,0,m_cdrdaoComm) ) + { + kdDebug() << "(K3bCdrdaoWriter) could not open socketpair for cdrdao remote messages" << endl; + } + else + { + delete m_comSock; + m_comSock = new QSocket(); + m_comSock->setSocket(m_cdrdaoComm[1]); + m_comSock->socketDevice()->setReceiveBufferSize(49152); + // magic number from Qt documentation + m_comSock->socketDevice()->setBlocking(false); + connect( m_comSock, SIGNAL(readyRead()), + this, SLOT(parseCdrdaoMessage())); + } +} + +K3bCdrdaoWriter::~K3bCdrdaoWriter() +{ + delete d->speedEst; + delete d; + + // close the socket + if( m_comSock ) { + m_comSock->close(); + ::close( m_cdrdaoComm[0] ); + } + delete m_process; + delete m_comSock; +} + + +int K3bCdrdaoWriter::fd() const +{ + if( m_process ) + return m_process->stdinFd(); + else + return -1; +} + + +bool K3bCdrdaoWriter::active() const +{ + return (m_process ? m_process->isRunning() : false); +} + + +void K3bCdrdaoWriter::prepareArgumentList() +{ + + // binary + *m_process << m_cdrdaoBinObject; + + // command + switch ( m_command ) + { + case COPY: + *m_process << "copy"; + setWriteArguments(); + setReadArguments(); + setCopyArguments(); + break; + case WRITE: + *m_process << "write"; + setWriteArguments(); + break; + case READ: + *m_process << "read-cd"; + // source device and source driver + if ( m_sourceDevice ) + *m_process << "--device" + << K3b::externalBinDeviceParameter(m_sourceDevice, m_cdrdaoBinObject); + if ( m_sourceDevice->cdrdaoDriver() != "auto" ) + *m_process << "--driver" << m_sourceDevice->cdrdaoDriver(); + else if( defaultToGenericMMC( m_sourceDevice, false ) ) { + kdDebug() << "(K3bCdrdaoWriter) defaulting to generic-mmc driver for " << m_sourceDevice->blockDeviceName() << endl; + *m_process << "--driver" << "generic-mmc"; + } + setReadArguments(); + break; + case BLANK: + *m_process << "blank"; + setBlankArguments(); + break; + } + + setCommonArguments(); +} + +void K3bCdrdaoWriter::setWriteArguments() +{ + // device and driver + *m_process << "--device" + << K3b::externalBinDeviceParameter(burnDevice(), m_cdrdaoBinObject); + + if( burnDevice()->cdrdaoDriver() != "auto" ) + { + *m_process << "--driver"; + if( burnDevice()->cdTextCapable() == 1 ) + *m_process << QString("%1:0x00000010").arg( burnDevice()->cdrdaoDriver() ); + else + *m_process << burnDevice()->cdrdaoDriver(); + } + else if( defaultToGenericMMC( burnDevice(), true ) ) { + kdDebug() << "(K3bCdrdaoWriter) defaulting to generic-mmc driver for " << burnDevice()->blockDeviceName() << endl; + *m_process << "--driver" << "generic-mmc:0x00000010"; + } + + // burn speed + if( d->usedSpeed != 0 ) + *m_process << "--speed" << QString("%1").arg(d->usedSpeed); + + //simulate + if( simulate() ) + *m_process << "--simulate"; + + // multi + if( m_multi ) + *m_process << "--multi"; + + // force + if( m_force ) + *m_process << "--force"; + + // burnproof + if ( !k3bcore->globalSettings()->burnfree() ) { + if( m_cdrdaoBinObject->hasFeature( "disable-burnproof" ) ) + *m_process << "--buffer-under-run-protection" << "0"; + else + emit infoMessage( i18n("Cdrdao %1 does not support disabling burnfree.").arg(m_cdrdaoBinObject->version), WARNING ); + } + + if( k3bcore->globalSettings()->force() ) { + *m_process << "--force"; + emit infoMessage( i18n("'Force unsafe operations' enabled."), WARNING ); + } + + bool manualBufferSize = + k3bcore->globalSettings()->useManualBufferSize(); + if( manualBufferSize ) { + // + // one buffer in cdrdao holds 1 second of audio data = 75 frames = 75 * 2352 bytes + // + int bufSizeInMb = k3bcore->globalSettings()->bufferSize(); + *m_process << "--buffers" << QString::number( bufSizeInMb*1024*1024/(75*2352) ); + } + + bool overburn = + k3bcore->globalSettings()->overburn(); + if( overburn ) { + if( m_cdrdaoBinObject->hasFeature("overburn") ) + *m_process << "--overburn"; + else + emit infoMessage( i18n("Cdrdao %1 does not support overburning.").arg(m_cdrdaoBinObject->version), WARNING ); + } + +} + +void K3bCdrdaoWriter::setReadArguments() +{ + // readRaw + if ( m_readRaw ) + *m_process << "--read-raw"; + + // subchan + if ( m_readSubchan != None ) + { + *m_process << "--read-subchan"; + switch ( m_readSubchan ) + { + case RW: + *m_process << "rw"; + break; + case RW_RAW: + *m_process << "rw_raw"; + break; + case None: + break; + } + } + + // TAO Source + if ( m_taoSource ) + *m_process << "--tao-source"; + + // TAO Source Adjust + if ( m_taoSourceAdjust != -1 ) + *m_process << "--tao-source-adjust" + << QString("%1").arg(m_taoSourceAdjust); + + // paranoia Mode + if ( m_paranoiaMode != -1 ) + *m_process << "--paranoia-mode" + << QString("%1").arg(m_paranoiaMode); + + // session + if ( m_session != -1 ) + *m_process << "--session" + << QString("%1").arg(m_session); + + // fast TOC + if ( m_fastToc ) + *m_process << "--fast-toc"; + +} + +void K3bCdrdaoWriter::setCopyArguments() +{ + // source device and source driver + *m_process << "--source-device" << K3b::externalBinDeviceParameter(m_sourceDevice, m_cdrdaoBinObject); + if ( m_sourceDevice->cdrdaoDriver() != "auto" ) + *m_process << "--source-driver" << m_sourceDevice->cdrdaoDriver(); + else if( defaultToGenericMMC( m_sourceDevice, false ) ) { + kdDebug() << "(K3bCdrdaoWriter) defaulting to generic-mmc driver for " << m_sourceDevice->blockDeviceName() << endl; + *m_process << "--source-driver" << "generic-mmc"; + } + + // on-the-fly + if ( m_onTheFly ) + *m_process << "--on-the-fly"; +} + +void K3bCdrdaoWriter::setBlankArguments() +{ + // device and driver + *m_process << "--device" + << K3b::externalBinDeviceParameter(burnDevice(), m_cdrdaoBinObject); + + if( burnDevice()->cdrdaoDriver() != "auto" ) + { + *m_process << "--driver"; + if( burnDevice()->cdTextCapable() == 1 ) + *m_process << QString("%1:0x00000010").arg( burnDevice()->cdrdaoDriver() ); + else + *m_process << burnDevice()->cdrdaoDriver(); + } + else if( defaultToGenericMMC( burnDevice(), true ) ) { + kdDebug() << "(K3bCdrdaoWriter) defaulting to generic-mmc driver for " << burnDevice()->blockDeviceName() << endl; + *m_process << "--driver" << "generic-mmc"; + } + + // burn speed + if( d->usedSpeed != 0 ) + *m_process << "--speed" << QString("%1").arg(d->usedSpeed); + + // blank-mode + *m_process << "--blank-mode"; + switch (m_blankMode) + { + case FULL: + *m_process << "full"; + break; + case MINIMAL: + *m_process << "minimal"; + break; + } +} + +void K3bCdrdaoWriter::setCommonArguments() +{ + + // additional user parameters from config + const QStringList& params = m_cdrdaoBinObject->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *m_process << *it; + + + // display debug info + *m_process << "-n" << "-v" << "2"; + + // we have the power to do what ever we want. ;) + *m_process << "--force"; + + // eject + if( m_eject && !m_forceNoEject ) + *m_process << "--eject"; + + // remote + *m_process << "--remote" << QString("%1").arg(m_cdrdaoComm[0]); + + // data File + if ( ! m_dataFile.isEmpty() ) + *m_process << "--datafile" << m_dataFile; + + // BIN/CUE + if ( ! m_cueFileLnk.isEmpty() ) + *m_process << m_cueFileLnk; + // TOC File + else if ( ! m_tocFile.isEmpty() ) + *m_process << m_tocFile; +} + +K3bCdrdaoWriter* K3bCdrdaoWriter::addArgument( const QString& arg ) +{ + *m_process << arg; + return this; +} + + +void K3bCdrdaoWriter::start() +{ + jobStarted(); + + d->speedEst->reset(); + + delete m_process; // kdelibs want this! + m_process = new K3bProcess(); + m_process->setRunPrivileged(true); + m_process->setSplitStdout(false); + m_process->setRawStdin(true); + connect( m_process, SIGNAL(stderrLine(const QString&)), + this, SLOT(slotStdLine(const QString&)) ); + connect( m_process, SIGNAL(processExited(KProcess*)), + this, SLOT(slotProcessExited(KProcess*)) ); + + m_canceled = false; + m_knownError = false; + + m_cdrdaoBinObject = k3bcore->externalBinManager()->binObject("cdrdao"); + + if( !m_cdrdaoBinObject ) { + emit infoMessage( i18n("Could not find %1 executable.").arg("cdrdao"), ERROR ); + jobFinished(false); + return; + } + + emit debuggingOutput( "Used versions", "cdrdao: " + m_cdrdaoBinObject->version ); + + if( !m_cdrdaoBinObject->copyright.isEmpty() ) + emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3").arg(m_cdrdaoBinObject->name()).arg(m_cdrdaoBinObject->version).arg(m_cdrdaoBinObject->copyright), INFO ); + + + // the message size changed in cdrdao 1.1.8) + if( m_cdrdaoBinObject->version >= K3bVersion( 1, 1, 8 ) ) + d->progressMsgSize = sizeof(ProgressMsg2); + else + d->progressMsgSize = sizeof(ProgressMsg); + + // since the --speed parameter is used several times in this code we + // determine the speed in auto once at the beginning + d->usedSpeed = burnSpeed(); + if( d->usedSpeed == 0 ) { + // try to determine the writeSpeed + // if it fails determineMaximalWriteSpeed() will return 0 and + // the choice is left to cdrdao + d->usedSpeed = burnDevice()->determineMaximalWriteSpeed(); + } + d->usedSpeed /= 175; + + switch ( m_command ) + { + case WRITE: + case COPY: + if (!m_tocFile.isEmpty()) + { + + // if tocfile is a cuesheet than create symlinks to *.cue and the binary listed inside the cuesheet. + // now works without the .bin extension too. + if ( !cueSheet() ) { + m_backupTocFile = m_tocFile + ".k3bbak"; + + // workaround, cdrdao deletes the tocfile when --remote parameter is set + if ( !KIO::NetAccess::copy(KURL(m_tocFile),KURL(m_backupTocFile), (QWidget*) 0) ) + { + kdDebug() << "(K3bCdrdaoWriter) could not backup " << m_tocFile << " to " << m_backupTocFile << endl; + emit infoMessage( i18n("Could not backup tocfile."), ERROR ); + jobFinished(false); + return; + } + } + } + break; + case BLANK: + case READ: + break; + } + prepareArgumentList(); + // set working dir to dir part of toc file (to allow rel names in toc-file) + m_process->setWorkingDirectory(QUrl(m_tocFile).dirPath()); + + kdDebug() << "***** cdrdao parameters:\n"; + const QValueList& args = m_process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) + { + s += *it + " "; + } + kdDebug() << s << flush << endl; + emit debuggingOutput("cdrdao command:", s); + + m_currentTrack = 0; + reinitParser(); + + switch ( m_command ) + { + case READ: + emit newSubTask( i18n("Preparing read process...") ); + break; + case WRITE: + emit newSubTask( i18n("Preparing write process...") ); + break; + case COPY: + emit newSubTask( i18n("Preparing copy process...") ); + break; + case BLANK: + emit newSubTask( i18n("Preparing blanking process...") ); + break; + } + + // FIXME: check the return value + if( K3b::isMounted( burnDevice() ) ) { + emit infoMessage( i18n("Unmounting medium"), INFO ); + K3b::unmount( burnDevice() ); + } + + // block the device (including certain checks) + k3bcore->blockDevice( burnDevice() ); + + // lock the device for good in this process since it will + // be opened in the growisofs process + burnDevice()->close(); + burnDevice()->usageLock(); + + if( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + // something went wrong when starting the program + // it "should" be the executable + kdDebug() << "(K3bCdrdaoWriter) could not start cdrdao" << endl; + emit infoMessage( i18n("Could not start %1.").arg("cdrdao"), K3bJob::ERROR ); + jobFinished(false); + } + else + { + switch ( m_command ) + { + case WRITE: + if( simulate() ) + { + emit infoMessage(i18n("Starting DAO simulation at %1x speed...").arg(d->usedSpeed), + K3bJob::INFO ); + emit newTask( i18n("Simulating") ); + } + else + { + emit infoMessage( i18n("Starting DAO writing at %1x speed...").arg(d->usedSpeed), K3bJob::INFO ); + emit newTask( i18n("Writing") ); + } + break; + case READ: + emit infoMessage(i18n("Starting reading..."), K3bJob::INFO ); + emit newTask( i18n("Reading") ); + break; + case COPY: + if( simulate() ) + { + emit infoMessage(i18n("Starting simulation copy at %1x speed...").arg(d->usedSpeed), K3bJob::INFO ); + emit newTask( i18n("Simulating") ); + } + else + { + emit infoMessage( i18n("Starting copy at %1x speed...").arg(d->usedSpeed), K3bJob::INFO ); + emit newTask( i18n("Copying") ); + } + break; + case BLANK: + emit infoMessage(i18n("Starting blanking..."), K3bJob::INFO ); + emit newTask( i18n("Blanking") ); + } + } +} + + +void K3bCdrdaoWriter::cancel() +{ + m_canceled = true; + + if( m_process ) { + if( m_process->isRunning() ) { + m_process->disconnect(); + m_process->kill(); + + // we need to unlock the device because cdrdao locked it while writing + // + // FIXME: try to determine wheater we are writing or reading and choose + // the device to unblock based on that result. + // + if( m_command == READ ) { + // FIXME: this is a hack + setBurnDevice( m_sourceDevice ); + } + + // this will unblock and eject the drive and emit the finished/canceled signals + K3bAbstractWriter::cancel(); + } + } +} + + +bool K3bCdrdaoWriter::cueSheet() +{ + + // TODO: do this in the K3bCueFileParser + + if ( m_tocFile.lower().endsWith( ".cue" ) ) { + QFile f( m_tocFile ); + if ( f.open( IO_ReadOnly ) ) { + QTextStream ts( &f ); + if ( !ts.eof() ) { + QString line = ts.readLine(); + f.close(); + int pos = line.find( "FILE \"" ); + if( pos < 0 ) + return false; + + pos += 6; + int endPos = line.find( "\" BINARY", pos+1 ); + if( endPos < 0 ) + return false; + + line = line.mid( pos, endPos-pos ); + QFileInfo fi( QFileInfo( m_tocFile ).dirPath() + "/" + QFileInfo( line ).fileName() ); + QString binpath = fi.filePath(); + kdDebug() << QString("K3bCdrdaoWriter::cueSheet() BinFilePath from CueFile: %1").arg( line ) << endl; + kdDebug() << QString("K3bCdrdaoWriter::cueSheet() absolute BinFilePath: %1").arg( binpath ) << endl; + + if ( !fi.exists() ) + return false; + + KTempFile tempF; + QString tempFile = tempF.name(); + tempF.unlink(); + + if ( symlink(QFile::encodeName( binpath ), QFile::encodeName( tempFile + ".bin") ) == -1 ) + return false; + if ( symlink(QFile::encodeName( m_tocFile ), QFile::encodeName( tempFile + ".cue") ) == -1 ) + return false; + + kdDebug() << QString("K3bCdrdaoWriter::cueSheet() symlink BinFileName: %1.bin").arg( tempFile ) << endl; + kdDebug() << QString("K3bCdrdaoWriter::cueSheet() symlink CueFileName: %1.cue").arg( tempFile ) << endl; + m_binFileLnk = tempFile + ".bin"; + m_cueFileLnk = tempFile + ".cue"; + return true; + } + } + } + + return false; +} + +void K3bCdrdaoWriter::slotStdLine( const QString& line ) +{ + parseCdrdaoLine(line); +} + + +void K3bCdrdaoWriter::slotProcessExited( KProcess* p ) +{ + // release the device within this process + burnDevice()->usageUnlock(); + + // unblock the device + k3bcore->unblockDevice( burnDevice() ); + + switch ( m_command ) + { + case WRITE: + case COPY: + if ( !m_binFileLnk.isEmpty() ) { + KIO::NetAccess::del(KURL::fromPathOrURL(m_cueFileLnk), (QWidget*) 0); + KIO::NetAccess::del(KURL::fromPathOrURL(m_binFileLnk), (QWidget*) 0); + } + else if( (!QFile::exists( m_tocFile ) || K3b::filesize( KURL::fromPathOrURL(m_tocFile) ) == 0 ) && !m_onTheFly ) + { + // cdrdao removed the tocfile :( + // we need to recover it + if ( !KIO::NetAccess::copy(KURL::fromPathOrURL(m_backupTocFile), KURL::fromPathOrURL(m_tocFile), (QWidget*) 0) ) + { + kdDebug() << "(K3bCdrdaoWriter) restoring tocfile " << m_tocFile << " failed." << endl; + emit infoMessage( i18n("Due to a bug in cdrdao the toc/cue file %1 has been deleted. " + "K3b was unable to restore it from the backup %2.").arg(m_tocFile).arg(m_backupTocFile), ERROR ); + } + else if ( !KIO::NetAccess::del(KURL::fromPathOrURL(m_backupTocFile), (QWidget*) 0) ) + { + kdDebug() << "(K3bCdrdaoWriter) delete tocfile backkup " << m_backupTocFile << " failed." << endl; + } + } + break; + case BLANK: + case READ: + break; + } + + if( m_canceled ) + return; + + if( p->normalExit() ) + { + switch( p->exitStatus() ) + { + case 0: + if( simulate() ) + emit infoMessage( i18n("Simulation successfully completed"), K3bJob::SUCCESS ); + else + switch ( m_command ) + { + case READ: + emit infoMessage( i18n("Reading successfully completed"), K3bJob::SUCCESS ); + break; + case WRITE: + emit infoMessage( i18n("Writing successfully completed"), K3bJob::SUCCESS ); + break; + case COPY: + emit infoMessage( i18n("Copying successfully completed"), K3bJob::SUCCESS ); + break; + case BLANK: + emit infoMessage( i18n("Blanking successfully completed"), K3bJob::SUCCESS ); + break; + } + + if( m_command == WRITE || m_command == COPY ) { + int s = d->speedEst->average(); + emit infoMessage( i18n("Average overall write speed: %1 KB/s (%2x)").arg(s).arg(KGlobal::locale()->formatNumber((double)s/150.0), 2), INFO ); + } + + jobFinished( true ); + break; + + default: + if( !m_knownError && !wasSourceUnreadable() ) { + emit infoMessage( i18n("%1 returned an unknown error (code %2).").arg(m_cdrdaoBinObject->name()).arg(p->exitStatus()), + K3bJob::ERROR ); + emit infoMessage( i18n("Please include the debugging output in your problem report."), K3bJob::ERROR ); + } + + jobFinished( false ); + break; + } + } + else + { + emit infoMessage( i18n("%1 did not exit cleanly.").arg("cdrdao"), K3bJob::ERROR ); + jobFinished( false ); + } +} + + +void K3bCdrdaoWriter::unknownCdrdaoLine( const QString& line ) +{ + if( line.contains( "at speed" ) ) + { + // parse the speed and inform the user if cdrdao switched it down + int pos = line.find( "at speed" ); + int po2 = line.find( QRegExp("\\D"), pos + 9 ); + int speed = line.mid( pos+9, po2-pos-9 ).toInt(); + if( speed < d->usedSpeed ) + { + emit infoMessage( i18n("Medium or burner do not support writing at %1x speed").arg(d->usedSpeed), K3bJob::WARNING ); + emit infoMessage( i18n("Switching down burn speed to %1x").arg(speed), K3bJob::WARNING ); + } + } +} + + +void K3bCdrdaoWriter::reinitParser() +{ + ::memset( &d->oldMsg, 0, sizeof(ProgressMsg2) ); + ::memset( &d->newMsg, 0, sizeof(ProgressMsg2) ); + + m_currentTrack=0; +} + +void K3bCdrdaoWriter::parseCdrdaoLine( const QString& str ) +{ + emit debuggingOutput( "cdrdao", str ); + // kdDebug() << "(cdrdaoparse)" << str << endl; + // find some messages from cdrdao + // ----------------------------------------------------------------------------------------- + if( (str).startsWith( "Warning" ) || (str).startsWith( "WARNING" ) || (str).startsWith( "ERROR" ) ) + { + parseCdrdaoError( str ); + } + else if( (str).startsWith( "Wrote" ) && !str.contains("blocks") ) + { + parseCdrdaoWrote( str ); + } + else if( (str).startsWith( "Executing power" ) ) + { + emit newSubTask( i18n("Executing Power calibration") ); + } + else if( (str).startsWith( "Power calibration successful" ) ) + { + emit infoMessage( i18n("Power calibration successful"), K3bJob::INFO ); + emit newSubTask( i18n("Preparing burn process...") ); + } + else if( (str).startsWith( "Flushing cache" ) ) + { + emit newSubTask( i18n("Flushing cache") ); + } + else if( (str).startsWith( "Writing CD-TEXT lead" ) ) + { + emit newSubTask( i18n("Writing CD-Text lead-in...") ); + } + else if( (str).startsWith( "Turning BURN-Proof on" ) ) + { + emit infoMessage( i18n("Turning BURN-Proof on"), K3bJob::INFO ); + } + else if( str.startsWith( "Copying" ) ) + { + emit infoMessage( str, K3bJob::INFO ); + } + else if( str.startsWith( "Found ISRC" ) ) + { + emit infoMessage( i18n("Found ISRC code"), K3bJob::INFO ); + } + else if( str.startsWith( "Found pre-gap" ) ) + { + emit infoMessage( i18n("Found pregap: %1").arg( str.mid(str.find(":")+1) ), K3bJob::INFO ); + } + else + unknownCdrdaoLine(str); +} + +void K3bCdrdaoWriter::parseCdrdaoError( const QString& line ) +{ + int pos = -1; + + if( line.contains( "No driver found" ) || + line.contains( "use option --driver" ) ) + { + emit infoMessage( i18n("No cdrdao driver found."), K3bJob::ERROR ); + emit infoMessage( i18n("Please select one manually in the device settings."), K3bJob::ERROR ); + emit infoMessage( i18n("For most current drives this would be 'generic-mmc'."), K3bJob::ERROR ); + m_knownError = true; + } + else if( line.contains( "Cannot setup device" ) ) + { + // no nothing... + } + else if( line.contains( "not ready") ) + { + emit infoMessage( i18n("Device not ready, waiting."),K3bJob::WARNING ); + } + else if( line.contains("Drive does not accept any cue sheet") ) + { + emit infoMessage( i18n("Cue sheet not accepted."), K3bJob::ERROR ); + m_knownError = true; + } + else if( (pos = line.find( "Illegal option" )) > 0 ) { + // ERROR: Illegal option: -wurst + emit infoMessage( i18n("No valid %1 option: %2").arg(m_cdrdaoBinObject->name()).arg(line.mid(pos+16)), + ERROR ); + m_knownError = true; + } + else if( line.contains( "exceeds capacity" ) ) { + emit infoMessage( i18n("Data does not fit on disk."), ERROR ); + if( m_cdrdaoBinObject->hasFeature("overburn") ) + emit infoMessage( i18n("Enable overburning in the advanced K3b settings to burn anyway."), INFO ); + m_knownError = true; + } + // else if( !line.contains( "remote progress message" ) ) +// emit infoMessage( line, K3bJob::ERROR ); +} + +void K3bCdrdaoWriter::parseCdrdaoWrote( const QString& line ) +{ + int pos, po2; + pos = line.find( "Wrote" ); + po2 = line.find( " ", pos + 6 ); + int processed = line.mid( pos+6, po2-pos-6 ).toInt(); + + pos = line.find( "of" ); + po2 = line.find( " ", pos + 3 ); + m_size = line.mid( pos+3, po2-pos-3 ).toInt(); + + d->speedEst->dataWritten( processed*1024 ); + + emit processedSize( processed, m_size ); +} + + +void K3bCdrdaoWriter::parseCdrdaoMessage() +{ + static const char msgSync[] = { 0xff, 0x00, 0xff, 0x00 }; + unsigned int avail = m_comSock->bytesAvailable(); + unsigned int msgs = avail / ( sizeof(msgSync)+d->progressMsgSize ); + unsigned int count = 0; + + if ( msgs < 1 ) + return; + else if ( msgs > 1) { + // move the read-index forward to the beginnig of the most recent message + count = ( msgs-1 ) * ( sizeof(msgSync)+d->progressMsgSize ); + m_comSock->at(count); + kdDebug() << "(K3bCdrdaoParser) " << msgs-1 << " message(s) skipped" << endl; + } + + while( count < avail ) { + + // search for msg sync + int state = 0; + char buf; + while( state < 4 ) { + buf = m_comSock->getch(); + ++count; + if( count == avail ) { + // kdDebug() << "(K3bCdrdaoParser) remote message sync not found (" << count << ")" << endl; + return; + } + + if( buf == msgSync[state] ) + ++state; + else + state = 0; + } + + if( (avail - count) < d->progressMsgSize ) { + kdDebug() << "(K3bCdrdaoParser) could not read complete remote message." << endl; + return; + } + + // read one message (the message size changed in cdrdao 1.1.8) + ::memset( &d->newMsg, 0, d->progressMsgSize ); + int size = m_comSock->readBlock( (char*)&d->newMsg, d->progressMsgSize); + if( size == -1 ) { + kdDebug() << "(K3bCdrdaoParser) read error" << endl; + return; + } + count += size; + + // sometimes the progress takes one step back (on my system when using paranoia-level 3) + // so we just use messages that are greater than the previous or first messages + if( d->oldMsg < d->newMsg + || ( d->newMsg.track == 1 && + d->newMsg.trackProgress <= 10 )) { + + if( d->newMsg.track != m_currentTrack ) { + switch( d->newMsg.status ) { + case PGSMSG_RCD_EXTRACTING: + emit nextTrack( d->newMsg.track, d->newMsg.totalTracks ); + break; + case PGSMSG_WCD_LEADIN: + emit newSubTask( i18n("Writing leadin ") ); + break; + case PGSMSG_WCD_DATA: + emit nextTrack( d->newMsg.track, d->newMsg.totalTracks ); + break; + case PGSMSG_WCD_LEADOUT: + emit newSubTask( i18n("Writing leadout ") ); + break; + } + + m_currentTrack = d->newMsg.track; + } + + if( d->newMsg.status == PGSMSG_WCD_LEADIN || d->newMsg.status == PGSMSG_WCD_LEADOUT ) { + // cdrdao >= 1.1.8 emits progress data when writing the lead-in and lead-out :) + emit subPercent( d->newMsg.totalProgress/10 ); + } + else { + emit subPercent( d->newMsg.trackProgress/10 ); + emit percent( d->newMsg.totalProgress/10 ); + } + + emit buffer(d->newMsg.bufferFillRate); + + if( d->progressMsgSize == (unsigned int)sizeof(ProgressMsg2) ) + emit deviceBuffer( d->newMsg.writerFillRate ); + + ::memcpy( &d->oldMsg, &d->newMsg, d->progressMsgSize ); + } + } +} + + +void K3bCdrdaoWriter::slotThroughput( int t ) +{ + // FIXME: determine sector size + emit writeSpeed( t, 150 ); +} + + +QString K3bCdrdaoWriter::findDriverFile( const K3bExternalBin* bin ) +{ + if( !bin ) + return QString::null; + + // cdrdao normally in (prefix)/bin and driver table in (prefix)/share/cdrdao + QString path = bin->path; + path.truncate( path.findRev("/") ); + path.truncate( path.findRev("/") ); + path += "/share/cdrdao/drivers"; + if( QFile::exists(path) ) + return path; + else { + kdDebug() << "(K3bCdrdaoWriter) could not find cdrdao driver table." << endl; + return QString::null; + } +} + + +// returns true if the driver file could be opened and no driver could be found +// TODO: cache the drivers +bool K3bCdrdaoWriter::defaultToGenericMMC( K3bDevice::Device* dev, bool writer ) +{ + QString driverTable = findDriverFile( m_cdrdaoBinObject ); + if( !driverTable.isEmpty() ) { + QFile f( driverTable ); + if( f.open( IO_ReadOnly ) ) { + // read all drivers + QStringList drivers; + QTextStream fStr( &f ); + while( !fStr.atEnd() ) { + QString line = fStr.readLine(); + if( line.isEmpty() ) + continue; + if( line[0] == '#' ) + continue; + if( line[0] == 'R' && writer ) + continue; + if( line[0] == 'W' && !writer ) + continue; + drivers.append(line); + } + + // search for the driver + for( QStringList::const_iterator it = drivers.begin(); it != drivers.end(); ++it ) { + if( (*it).section( '|', 1, 1 ) == dev->vendor() && + (*it).section( '|', 2, 2 ) == dev->description() ) + return false; + } + + // no driver found + return true; + } + else { + kdDebug() << "(K3bCdrdaoWriter) could not open driver table " << driverTable << endl; + return false; + } + } + else + return false; +} + + +#include "k3bcdrdaowriter.moc" diff --git a/libk3b/projects/k3bcdrdaowriter.h b/libk3b/projects/k3bcdrdaowriter.h new file mode 100644 index 0000000..94a0c9f --- /dev/null +++ b/libk3b/projects/k3bcdrdaowriter.h @@ -0,0 +1,157 @@ +/* + * + * $Id: k3bcdrdaowriter.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * Klaus-Dieter Krannich + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3B_CDRDAO_WRITER_H +#define K3B_CDRDAO_WRITER_H + + +#include "k3babstractwriter.h" + +class K3bExternalBin; +class K3bProcess; +class KProcess; +class K3bDevice::Device; +class QSocket; + + + +class K3bCdrdaoWriter : public K3bAbstractWriter +{ + Q_OBJECT + + public: + + enum Command { WRITE, COPY, READ, BLANK }; + enum BlankMode { FULL, MINIMAL }; + enum SubMode { None, RW, RW_RAW }; + + K3bCdrdaoWriter( K3bDevice::Device* dev, K3bJobHandler*, + QObject* parent = 0, const char* name = 0 ); + ~K3bCdrdaoWriter(); + + /** + * to be used in chain: addArgument(x)->addArgument(y) + */ + K3bCdrdaoWriter* addArgument( const QString& ); + K3bDevice::Device* sourceDevice() { return m_sourceDevice; }; + + int fd() const; + + bool active() const; + + private: + void reinitParser(); + void parseCdrdaoLine( const QString& line ); + void parseCdrdaoWrote( const QString& line ); + void parseCdrdaoError( const QString& line ); + + public slots: + void start(); + void cancel(); + + // options + // --------------------- + void setCommand( int c ) { m_command = c; } + void setBlankMode( int b ) { m_blankMode = b; } + void setMulti( bool b ) { m_multi = b; } + void setForce( bool b ) { m_force = b; } + void setOnTheFly( bool b ) { m_onTheFly = b; } + void setDataFile( const QString& s ) { m_dataFile = s; } + void setTocFile( const QString& s ) { m_tocFile = s; } + + void setSourceDevice( K3bDevice::Device* dev ) { m_sourceDevice = dev; } + void setFastToc( bool b ) { m_fastToc = b; } + void setReadRaw( bool b ) { m_readRaw = b; } + void setReadSubchan(SubMode m) { m_readSubchan=m; }; + void setParanoiaMode( int i ) { m_paranoiaMode = i; } + void setTaoSource(bool b) { m_taoSource=b; }; + void setTaoSourceAdjust(int a) { m_taoSourceAdjust=a; }; + void setSession(int s) { m_session=s; }; + void setEject(bool e) { m_eject=e; }; +// --------------------- + + /** + * If set true the job ignores the global K3b setting + * and does not eject the CD-RW after finishing + */ + void setForceNoEject( bool b ) { m_forceNoEject = b; } + + private slots: + void slotStdLine( const QString& line ); + void slotProcessExited(KProcess*); + void parseCdrdaoMessage(); + void slotThroughput( int t ); + + private: + void unknownCdrdaoLine( const QString& ); + void prepareArgumentList(); + void setWriteArguments(); + void setReadArguments(); + void setCopyArguments(); + void setBlankArguments(); + void setCommonArguments(); + + bool cueSheet(); + + QString findDriverFile( const K3bExternalBin* bin ); + bool defaultToGenericMMC( K3bDevice::Device* dev, bool writer ); + + // options + // --------------------- + int m_command; + int m_blankMode; + K3bDevice::Device* m_sourceDevice; + QString m_dataFile; + QString m_tocFile; + QString m_cueFileLnk; + QString m_binFileLnk; + QString m_backupTocFile; + bool m_readRaw; + bool m_multi; + bool m_force; + bool m_onTheFly; + bool m_fastToc; + SubMode m_readSubchan; + bool m_taoSource; + int m_taoSourceAdjust; + int m_paranoiaMode; + int m_session; + bool m_eject; + // --------------------- + + const K3bExternalBin* m_cdrdaoBinObject; + K3bProcess* m_process; + + int m_cdrdaoComm[2]; + QSocket *m_comSock; + + bool m_canceled; + + bool m_knownError; + +// parser + + int m_size; + int m_currentTrack; + + bool m_forceNoEject; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/k3bcdrecordwriter.cpp b/libk3b/projects/k3bcdrecordwriter.cpp new file mode 100644 index 0000000..e87c767 --- /dev/null +++ b/libk3b/projects/k3bcdrecordwriter.cpp @@ -0,0 +1,810 @@ +/* + * + * $Id: k3bcdrecordwriter.cpp 690529 2007-07-21 10:51:47Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include + + +#include "k3bcdrecordwriter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + + +class K3bCdrecordWriter::Private +{ +public: + Private() + : cdTextFile(0) { + } + + K3bThroughputEstimator* speedEst; + bool canceled; + bool usingBurnfree; + int usedSpeed; + + struct Track { + int size; + bool audio; + }; + + QValueList tracks; + + KTempFile* cdTextFile; +}; + + +K3bCdrecordWriter::K3bCdrecordWriter( K3bDevice::Device* dev, K3bJobHandler* hdl, + QObject* parent, const char* name ) + : K3bAbstractWriter( dev, hdl, parent, name ), + m_clone(false), + m_cue(false), + m_forceNoEject(false) +{ + d = new Private(); + d->speedEst = new K3bThroughputEstimator( this ); + connect( d->speedEst, SIGNAL(throughput(int)), + this, SLOT(slotThroughput(int)) ); + + m_process = 0; + m_writingMode = K3b::TAO; +} + + +K3bCdrecordWriter::~K3bCdrecordWriter() +{ + delete d->cdTextFile; + delete d; + delete m_process; +} + + +bool K3bCdrecordWriter::active() const +{ + return ( m_process && m_process->isRunning() ); +} + + +int K3bCdrecordWriter::fd() const +{ + if( m_process ) + return m_process->stdinFd(); + else + return -1; +} + + +void K3bCdrecordWriter::setDao( bool b ) +{ + m_writingMode = ( b ? K3b::DAO : K3b::TAO ); +} + +void K3bCdrecordWriter::setCueFile( const QString& s) +{ + m_cue = true; + m_cueFile = s; + + // cuefile only works in DAO mode + setWritingMode( K3b::DAO ); +} + +void K3bCdrecordWriter::setClone( bool b ) +{ + m_clone = b; +} + + +void K3bCdrecordWriter::setWritingMode( int mode ) +{ + if( mode == K3b::DAO || + mode == K3b::TAO || + mode == K3b::RAW ) + m_writingMode = mode; + else + kdError() << "(K3bCdrecordWriter) wrong writing mode: " << mode << endl; +} + + +void K3bCdrecordWriter::prepareProcess() +{ + if( m_process ) delete m_process; // kdelibs want this! + m_process = new K3bProcess(); + m_process->setRunPrivileged(true); + // m_process->setPriority( KProcess::PrioHighest ); + m_process->setSplitStdout(true); + m_process->setSuppressEmptyLines(true); + m_process->setRawStdin(true); // we only use stdin when writing on-the-fly + connect( m_process, SIGNAL(stdoutLine(const QString&)), this, SLOT(slotStdLine(const QString&)) ); + connect( m_process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotStdLine(const QString&)) ); + connect( m_process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited(KProcess*)) ); + + m_cdrecordBinObject = k3bcore->externalBinManager()->binObject("cdrecord"); + + if( !m_cdrecordBinObject ) + return; + + *m_process << m_cdrecordBinObject; + + // display progress + *m_process << "-v"; + + if( m_cdrecordBinObject->hasFeature( "gracetime") ) + *m_process << "gracetime=2"; // 2 is the lowest allowed value (Joerg, why do you do this to us?) + + // Again we assume the device to be set! + *m_process << QString("dev=%1").arg(K3b::externalBinDeviceParameter(burnDevice(), m_cdrecordBinObject)); + + d->usedSpeed = burnSpeed(); + if( d->usedSpeed == 0 ) { + // try to determine the writeSpeed + // if it fails determineMaximalWriteSpeed() will return 0 and + // the choice is left to cdrecord + d->usedSpeed = burnDevice()->determineMaximalWriteSpeed(); + } + d->usedSpeed /= 175; + if( d->usedSpeed != 0 ) + *m_process << QString("speed=%1").arg(d->usedSpeed); + + if( m_writingMode == K3b::DAO || m_cue ) { + if( burnDevice()->dao() ) + *m_process << "-dao"; + else { + if( m_cdrecordBinObject->hasFeature( "tao" ) ) + *m_process << "-tao"; + emit infoMessage( i18n("Writer does not support disk at once (DAO) recording"), WARNING ); + } + } + else if( m_writingMode == K3b::RAW ) { + if( burnDevice()->supportsWritingMode( K3bDevice::RAW_R96R ) ) + *m_process << "-raw96r"; + else if( burnDevice()->supportsWritingMode( K3bDevice::RAW_R16 ) ) + *m_process << "-raw16"; + else if( burnDevice()->supportsWritingMode( K3bDevice::RAW_R96P ) ) + *m_process << "-raw96p"; + else { + emit infoMessage( i18n("Writer does not support raw writing."), WARNING ); + if( m_cdrecordBinObject->hasFeature( "tao" ) ) + *m_process << "-tao"; + } + } + else if( m_cdrecordBinObject->hasFeature( "tao" ) ) + *m_process << "-tao"; + + if( simulate() ) + *m_process << "-dummy"; + + d->usingBurnfree = false; + if( k3bcore->globalSettings()->burnfree() ) { + if( burnDevice()->burnproof() ) { + + d->usingBurnfree = true; + + // with cdrecord 1.11a02 burnproof was renamed to burnfree + if( m_cdrecordBinObject->hasFeature( "burnproof" ) ) + *m_process << "driveropts=burnproof"; + else + *m_process << "driveropts=burnfree"; + } + else + emit infoMessage( i18n("Writer does not support buffer underrun free recording (Burnfree)"), WARNING ); + } + + if( k3bcore->globalSettings()->force() ) { + *m_process << "-force"; + emit infoMessage( i18n("'Force unsafe operations' enabled."), WARNING ); + } + + if( m_cue ) { + m_process->setWorkingDirectory(QUrl(m_cueFile).dirPath()); + *m_process << QString("cuefile=%1").arg( m_cueFile ); + } + + if( m_clone ) + *m_process << "-clone"; + + if( m_rawCdText.size() > 0 ) { + delete d->cdTextFile; + d->cdTextFile = new K3bTempFile( QString::null, ".dat" ); + d->cdTextFile->setAutoDelete(true); + d->cdTextFile->file()->writeBlock( m_rawCdText ); + d->cdTextFile->close(); + + *m_process << "textfile=" + d->cdTextFile->name(); + } + + if( k3bcore->globalSettings()->ejectMedia() && + !m_forceNoEject ) + *m_process << "-eject"; + + bool manualBufferSize = k3bcore->globalSettings()->useManualBufferSize(); + if( manualBufferSize ) { + *m_process << QString("fs=%1m").arg( k3bcore->globalSettings()->bufferSize() ); + } + + bool overburn = k3bcore->globalSettings()->overburn(); + if( overburn ) + if( m_cdrecordBinObject->hasFeature("overburn") ) + *m_process << "-overburn"; + else + emit infoMessage( i18n("Cdrecord %1 does not support overburning.").arg(m_cdrecordBinObject->version), WARNING ); + + // additional user parameters from config + const QStringList& params = m_cdrecordBinObject->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *m_process << *it; + + // add the user parameters + for( QStringList::const_iterator it = m_arguments.begin(); it != m_arguments.end(); ++it ) + *m_process << *it; +} + + +K3bCdrecordWriter* K3bCdrecordWriter::addArgument( const QString& arg ) +{ + m_arguments.append( arg ); + return this; +} + + +void K3bCdrecordWriter::clearArguments() +{ + m_arguments.clear(); +} + + +void K3bCdrecordWriter::start() +{ + jobStarted(); + + d->canceled = false; + d->speedEst->reset(); + + prepareProcess(); + + if( !m_cdrecordBinObject ) { + emit infoMessage( i18n("Could not find %1 executable.").arg("cdrecord"), ERROR ); + jobFinished(false); + return; + } + + emit debuggingOutput( "Used versions", "cdrecord: " + m_cdrecordBinObject->version ); + + if( !m_cdrecordBinObject->copyright.isEmpty() ) + emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3") + .arg(m_cdrecordBinObject->hasFeature( "wodim" ) ? "Wodim" : "Cdrecord" ) + .arg(m_cdrecordBinObject->version) + .arg(m_cdrecordBinObject->copyright), INFO ); + + + kdDebug() << "***** " << m_cdrecordBinObject->name() << " parameters:\n"; + const QValueList& args = m_process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << flush << endl; + emit debuggingOutput( m_cdrecordBinObject->name() + " command:", s); + + m_currentTrack = 0; + m_cdrecordError = UNKNOWN; + m_totalTracksParsed = false; + m_alreadyWritten = 0; + d->tracks.clear(); + m_totalSize = 0; + + emit newSubTask( i18n("Preparing write process...") ); + + // FIXME: check the return value + if( K3b::isMounted( burnDevice() ) ) { + emit infoMessage( i18n("Unmounting medium"), INFO ); + K3b::unmount( burnDevice() ); + } + + // block the device (including certain checks) + k3bcore->blockDevice( burnDevice() ); + + // lock the device for good in this process since it will + // be opened in the growisofs process + burnDevice()->close(); + burnDevice()->usageLock(); + + if( !m_process->start( KProcess::NotifyOnExit, KProcess::All ) ) { + // something went wrong when starting the program + // it "should" be the executable + kdDebug() << "(K3bCdrecordWriter) could not start " << m_cdrecordBinObject->name() << endl; + emit infoMessage( i18n("Could not start %1.").arg(m_cdrecordBinObject->name()), K3bJob::ERROR ); + jobFinished(false); + } + else { + if( simulate() ) { + emit newTask( i18n("Simulating") ); + emit infoMessage( i18n("Starting %1 simulation at %2x speed...") + .arg(K3b::writingModeString(m_writingMode)) + .arg(d->usedSpeed), + K3bJob::INFO ); + } + else { + emit newTask( i18n("Writing") ); + emit infoMessage( i18n("Starting %1 writing at %2x speed...") + .arg(K3b::writingModeString(m_writingMode)) + .arg(d->usedSpeed), + K3bJob::INFO ); + } + } +} + + +void K3bCdrecordWriter::cancel() +{ + if( active() ) { + d->canceled = true; + if( m_process && m_process->isRunning() ) + m_process->kill(); + } +} + + +void K3bCdrecordWriter::slotStdLine( const QString& line ) +{ + static QRegExp s_burnfreeCounterRx( "^BURN\\-Free\\swas\\s(\\d+)\\stimes\\sused" ); + static QRegExp s_burnfreeCounterRxPredict( "^Total\\sof\\s(\\d+)\\s\\spossible\\sbuffer\\sunderruns\\spredicted" ); + + // tracknumber: cap(1) + // done: cap(2) + // complete: cap(3) + // fifo: cap(4) (it seems as if some patched cdrecord versions do not emit the fifo info but only the buf... :( + // buffer: cap(5) + static QRegExp s_progressRx( "Track\\s(\\d\\d)\\:\\s*(\\d*)\\sof\\s*(\\d*)\\sMB\\swritten\\s(?:\\(fifo\\s*(\\d*)\\%\\)\\s*)?(?:\\[buf\\s*(\\d*)\\%\\])?.*" ); + + emit debuggingOutput( m_cdrecordBinObject->name(), line ); + + // + // Progress and toc parsing + // + + if( line.startsWith( "Track " ) ) { + if( !m_totalTracksParsed ) { + // this is not the progress display but the list of tracks that will get written + // we always extract the tracknumber to get the highest at last + bool ok; + int tt = line.mid( 6, 2 ).toInt(&ok); + + if( ok ) { + struct Private::Track track; + track.audio = ( line.mid( 10, 5 ) == "audio" ); + + m_totalTracks = tt; + + int sizeStart = line.find( QRegExp("\\d"), 10 ); + int sizeEnd = line.find( "MB", sizeStart ); + track.size = line.mid( sizeStart, sizeEnd-sizeStart ).toInt(&ok); + + if( ok ) { + d->tracks.append(track); + m_totalSize += track.size; + } + else + kdDebug() << "(K3bCdrecordWriter) track number parse error: " + << line.mid( sizeStart, sizeEnd-sizeStart ) << endl; + } + else + kdDebug() << "(K3bCdrecordWriter) track number parse error: " + << line.mid( 6, 2 ) << endl; + } + + else if( s_progressRx.exactMatch( line ) ) { + // int num = s_progressRx.cap(1).toInt(); + int made = s_progressRx.cap(2).toInt(); + int size = s_progressRx.cap(3).toInt(); + int fifo = s_progressRx.cap(4).toInt(); + + emit buffer( fifo ); + m_lastFifoValue = fifo; + + if( s_progressRx.numCaptures() > 4 ) + emit deviceBuffer( s_progressRx.cap(5).toInt() ); + + // + // cdrecord's output sucks a bit. + // we get track sizes that differ from the sizes in the progress + // info since these are dependant on the writing mode. + // so we just use the track sizes and do a bit of math... + // + + if( d->tracks.count() > m_currentTrack-1 && size > 0 ) { + double convV = (double)d->tracks[m_currentTrack-1].size/(double)size; + made = (int)((double)made * convV); + size = d->tracks[m_currentTrack-1].size; + } + else { + kdError() << "(K3bCdrecordWriter) Did not parse all tracks sizes!" << endl; + } + + if( size > 0 ) { + emit processedSubSize( made, size ); + emit subPercent( 100*made/size ); + } + + if( m_totalSize > 0 ) { + emit processedSize( m_alreadyWritten+made, m_totalSize ); + emit percent( 100*(m_alreadyWritten+made)/m_totalSize ); + } + + d->speedEst->dataWritten( (m_alreadyWritten+made)*1024 ); + } + } + + // + // Cdrecord starts all error and warning messages with it's path + // With Debian's script it starts with cdrecord (or /usr/bin/cdrecord or whatever! I hate this script!) + // + + else if( line.startsWith( "cdrecord" ) || + line.startsWith( m_cdrecordBinObject->path ) || + line.startsWith( m_cdrecordBinObject->path.left(m_cdrecordBinObject->path.length()-5) ) ) { + // get rid of the path and the following colon and space + QString errStr = line.mid( line.find(':') + 2 ); + + if( errStr.startsWith( "Drive does not support SAO" ) ) { + emit infoMessage( i18n("DAO (Disk At Once) recording not supported with this writer"), K3bJob::ERROR ); + emit infoMessage( i18n("Please choose TAO (Track At Once) and try again"), K3bJob::ERROR ); + } + else if( errStr.startsWith( "Drive does not support RAW" ) ) { + emit infoMessage( i18n("RAW recording not supported with this writer"), K3bJob::ERROR ); + } + else if( errStr.startsWith("Input/output error.") ) { + emit infoMessage( i18n("Input/output error. Not necessarily serious."), WARNING ); + } + else if( errStr.startsWith("shmget failed") ) { + m_cdrecordError = SHMGET_FAILED; + } + else if( errStr.startsWith("OPC failed") ) { + m_cdrecordError = OPC_FAILED; + } + else if( errStr.startsWith( "Drive needs to reload the media" ) ) { + emit infoMessage( i18n("Reloading of medium required"), K3bJob::INFO ); + } + else if( errStr.startsWith( "The current problem looks like a buffer underrun" ) ) { + if( m_cdrecordError == UNKNOWN ) // it is almost never a buffer underrun these days. + m_cdrecordError = BUFFER_UNDERRUN; + } + else if( errStr.startsWith("WARNING: Data may not fit") ) { + bool overburn = k3bcore->globalSettings()->overburn(); + if( overburn && m_cdrecordBinObject->hasFeature("overburn") ) + emit infoMessage( i18n("Trying to write more than the official disk capacity"), K3bJob::WARNING ); + m_cdrecordError = OVERSIZE; + } + else if( errStr.startsWith("Bad Option") ) { + m_cdrecordError = BAD_OPTION; + // parse option + int pos = line.find( "Bad Option" ) + 13; + int len = line.length() - pos - 1; + emit infoMessage( i18n("No valid %1 option: %2").arg(m_cdrecordBinObject->name()).arg(line.mid(pos, len)), + ERROR ); + } + else if( errStr.startsWith("Cannot set speed/dummy") ) { + m_cdrecordError = CANNOT_SET_SPEED; + } + else if( errStr.startsWith("Cannot open new session") ) { + m_cdrecordError = CANNOT_OPEN_NEW_SESSION; + } + else if( errStr.startsWith("Cannot send CUE sheet") ) { + m_cdrecordError = CANNOT_SEND_CUE_SHEET; + } + else if( errStr.startsWith( "Trying to use ultra high speed" ) || + errStr.startsWith( "Trying to use high speed" ) || + errStr.startsWith( "Probably trying to use ultra high speed" ) || + errStr.startsWith( "You did use a high speed medium on an improper writer" ) || + errStr.startsWith( "You did use a ultra high speed medium on an improper writer" ) ) { + m_cdrecordError = HIGH_SPEED_MEDIUM; + } + else if( errStr.startsWith( "You may have used an ultra low speed medium" ) ) { + m_cdrecordError = LOW_SPEED_MEDIUM; + } + else if( errStr.startsWith( "Permission denied. Cannot open" ) || + errStr.startsWith( "Operation not permitted." ) ) { + m_cdrecordError = PERMISSION_DENIED; + } + else if( errStr.startsWith( "Can only copy session # 1") ) { + emit infoMessage( i18n("Only session 1 will be cloned."), WARNING ); + } + else if( errStr == "Cannot fixate disk." ) { + emit infoMessage( i18n("Unable to fixate the disk."), ERROR ); + if( m_cdrecordError == UNKNOWN ) + m_cdrecordError = CANNOT_FIXATE_DISK; + } + else if( errStr == "A write error occurred." ) { + m_cdrecordError = WRITE_ERROR; + } + else if( errStr.startsWith( "Try again with cdrecord blank=all." ) ) { + m_cdrecordError = BLANK_FAILED; + } + } + + // + // All other messages + // + + else if( line.contains( "at speed" ) ) { + // parse the speed and inform the user if cdrdao switched it down + int pos = line.find( "at speed" ); + int pos2 = line.find( "in", pos+9 ); + int speed = static_cast( line.mid( pos+9, pos2-pos-10 ).toDouble() ); // cdrecord-dvd >= 2.01a25 uses 8.0 and stuff + if( speed != d->usedSpeed ) { + emit infoMessage( i18n("Medium or burner do not support writing at %1x speed").arg(d->usedSpeed), K3bJob::WARNING ); + if( speed > d->usedSpeed ) + emit infoMessage( i18n("Switching burn speed up to %1x").arg(speed), K3bJob::WARNING ); + else + emit infoMessage( i18n("Switching burn speed down to %1x").arg(speed), K3bJob::WARNING ); + } + } + else if( line.startsWith( "Starting new" ) ) { + m_totalTracksParsed = true; + if( m_currentTrack > 0 ) {// nothing has been written at the start of track 1 + if( d->tracks.count() > m_currentTrack-1 ) + m_alreadyWritten += d->tracks[m_currentTrack-1].size; + else + kdError() << "(K3bCdrecordWriter) Did not parse all tracks sizes!" << endl; + } + else + emit infoMessage( i18n("Starting disc write"), INFO ); + + m_currentTrack++; + + if( m_currentTrack > d->tracks.count() ) { + kdDebug() << "(K3bCdrecordWriter) need to add dummy track struct." << endl; + struct Private::Track t; + t.size = 1; + t.audio = false; + d->tracks.append(t); + } + + kdDebug() << "(K3bCdrecordWriter) writing track " << m_currentTrack << " of " << m_totalTracks << " tracks." << endl; + emit nextTrack( m_currentTrack, m_totalTracks ); + } + else if( line.startsWith( "Fixating" ) ) { + emit newSubTask( i18n("Closing Session") ); + } + else if( line.startsWith( "Writing lead-in" ) ) { + m_totalTracksParsed = true; + emit newSubTask( i18n("Writing Leadin") ); + } + else if( line.startsWith( "Writing Leadout") ) { + emit newSubTask( i18n("Writing Leadout") ); + } + else if( line.startsWith( "Writing pregap" ) ) { + emit newSubTask( i18n("Writing pregap") ); + } + else if( line.startsWith( "Performing OPC" ) ) { + emit infoMessage( i18n("Performing Optimum Power Calibration"), K3bJob::INFO ); + } + else if( line.startsWith( "Sending" ) ) { + emit infoMessage( i18n("Sending CUE sheet"), K3bJob::INFO ); + } + else if( line.startsWith( "Turning BURN-Free on" ) || line.startsWith( "BURN-Free is ON") ) { + emit infoMessage( i18n("Enabled Burnfree"), K3bJob::INFO ); + } + else if( line.startsWith( "Turning BURN-Free off" ) ) { + emit infoMessage( i18n("Disabled Burnfree"), K3bJob::WARNING ); + } + else if( line.startsWith( "Re-load disk and hit" ) ) { + // this happens on some notebooks where cdrecord is not able to close the + // tray itself, so we need to ask the user to do so + blockingInformation( i18n("Please reload the medium and press 'ok'"), + i18n("Unable to close the tray") ); + + // now send a to cdrecord + // hopefully this will do it since I have no possibility to test it! + ::write( fd(), "\n", 1 ); + } + else if( s_burnfreeCounterRx.search( line ) ) { + bool ok; + int num = s_burnfreeCounterRx.cap(1).toInt(&ok); + if( ok ) + emit infoMessage( i18n("Burnfree was used 1 time.", "Burnfree was used %n times.", num), INFO ); + } + else if( s_burnfreeCounterRxPredict.search( line ) ) { + bool ok; + int num = s_burnfreeCounterRxPredict.cap(1).toInt(&ok); + if( ok ) + emit infoMessage( i18n("Buffer was low 1 time.", "Buffer was low %n times.", num), INFO ); + } + else if( line.contains("Medium Error") ) { + m_cdrecordError = MEDIUM_ERROR; + } + else if( line.startsWith( "Error trying to open" ) && line.contains( "(Device or resource busy)" ) ) { + m_cdrecordError = DEVICE_BUSY; + } + else { + // debugging + kdDebug() << "(" << m_cdrecordBinObject->name() << ") " << line << endl; + } +} + + +void K3bCdrecordWriter::slotProcessExited( KProcess* p ) +{ + // remove temporary cdtext file + delete d->cdTextFile; + d->cdTextFile = 0; + + // release the device within this process + burnDevice()->usageUnlock(); + + // unblock the device + k3bcore->unblockDevice( burnDevice() ); + + if( d->canceled ) { + // this will unblock and eject the drive and emit the finished/canceled signals + K3bAbstractWriter::cancel(); + return; + } + + + if( p->normalExit() ) { + switch( p->exitStatus() ) { + case 0: + { + if( simulate() ) + emit infoMessage( i18n("Simulation successfully completed"), K3bJob::SUCCESS ); + else + emit infoMessage( i18n("Writing successfully completed"), K3bJob::SUCCESS ); + + int s = d->speedEst->average(); + emit infoMessage( i18n("Average overall write speed: %1 KB/s (%2x)").arg(s).arg(KGlobal::locale()->formatNumber((double)s/150.0), 2), INFO ); + + jobFinished( true ); + } + break; + + default: + kdDebug() << "(K3bCdrecordWriter) error: " << p->exitStatus() << endl; + + if( m_cdrecordError == UNKNOWN && m_lastFifoValue <= 3 ) + m_cdrecordError = BUFFER_UNDERRUN; + + switch( m_cdrecordError ) { + case OVERSIZE: + if( k3bcore->globalSettings()->overburn() && + m_cdrecordBinObject->hasFeature("overburn") ) + emit infoMessage( i18n("Data did not fit on disk."), ERROR ); + else { + emit infoMessage( i18n("Data does not fit on disk."), ERROR ); + if( m_cdrecordBinObject->hasFeature("overburn") ) + emit infoMessage( i18n("Enable overburning in the advanced K3b settings to burn anyway."), INFO ); + } + break; + case BAD_OPTION: + // error message has already been emited earlier since we needed the actual line + break; + case SHMGET_FAILED: + emit infoMessage( i18n("%1 could not reserve shared memory segment of requested size.").arg(m_cdrecordBinObject->name()), ERROR ); + emit infoMessage( i18n("Probably you chose a too large buffer size."), ERROR ); + break; + case OPC_FAILED: + emit infoMessage( i18n("OPC failed. Probably the writer does not like the medium."), ERROR ); + break; + case CANNOT_SET_SPEED: + emit infoMessage( i18n("Unable to set write speed to %1.").arg(d->usedSpeed), ERROR ); + emit infoMessage( i18n("Probably this is lower than your writer's lowest writing speed."), ERROR ); + break; + case CANNOT_SEND_CUE_SHEET: + emit infoMessage( i18n("Unable to send CUE sheet."), ERROR ); + if( m_writingMode == K3b::DAO ) + emit infoMessage( i18n("Sometimes using TAO writing mode solves this issue."), ERROR ); + break; + case CANNOT_OPEN_NEW_SESSION: + emit infoMessage( i18n("Unable to open new session."), ERROR ); + emit infoMessage( i18n("Probably a problem with the medium."), ERROR ); + break; + case CANNOT_FIXATE_DISK: + emit infoMessage( i18n("The disk might still be readable."), ERROR ); + if( m_writingMode == K3b::TAO && burnDevice()->dao() ) + emit infoMessage( i18n("Try DAO writing mode."), ERROR ); + break; + case PERMISSION_DENIED: + emit infoMessage( i18n("%1 has no permission to open the device.").arg("Cdrecord"), ERROR ); +#ifdef HAVE_K3BSETUP + emit infoMessage( i18n("You may use K3bsetup2 to solve this problem."), ERROR ); +#endif + break; + case BUFFER_UNDERRUN: + emit infoMessage( i18n("Probably a buffer underrun occurred."), ERROR ); + if( !d->usingBurnfree && burnDevice()->burnproof() ) + emit infoMessage( i18n("Please enable Burnfree or choose a lower burning speed."), ERROR ); + else + emit infoMessage( i18n("Please choose a lower burning speed."), ERROR ); + break; + case HIGH_SPEED_MEDIUM: + emit infoMessage( i18n("Found a high-speed medium not suitable for the writer being used."), ERROR ); + emit infoMessage( i18n("Use the 'force unsafe operations' option to ignore this."), ERROR ); + break; + case LOW_SPEED_MEDIUM: + emit infoMessage( i18n("Found a low-speed medium not suitable for the writer being used."), ERROR ); + emit infoMessage( i18n("Use the 'force unsafe operations' option to ignore this."), ERROR ); + break; + case MEDIUM_ERROR: + emit infoMessage( i18n("Most likely the burning failed due to low-quality media."), ERROR ); + break; + case DEVICE_BUSY: + emit infoMessage( i18n("Another application is blocking the device (most likely automounting)."), ERROR ); + break; + case WRITE_ERROR: + emit infoMessage( i18n("A write error occurred."), ERROR ); + if( m_writingMode == K3b::DAO ) + emit infoMessage( i18n("Sometimes using TAO writing mode solves this issue."), ERROR ); + break; + case BLANK_FAILED: + emit infoMessage( i18n("Some drives do not support all erase types."), ERROR ); + emit infoMessage( i18n("Try again using 'Complete' erasing."), ERROR ); + break; + case UNKNOWN: + if( p->exitStatus() == 12 && K3b::kernelVersion() >= K3bVersion( 2, 6, 8 ) && m_cdrecordBinObject->hasFeature( "suidroot" ) ) { + emit infoMessage( i18n("Since kernel version 2.6.8 cdrecord cannot use SCSI transport when running suid root anymore."), ERROR ); + emit infoMessage( i18n("You may use K3bSetup to solve this problem or remove the suid bit manually."), ERROR ); + } + else if( !wasSourceUnreadable() ) { + emit infoMessage( i18n("%1 returned an unknown error (code %2).") + .arg(m_cdrecordBinObject->name()).arg(p->exitStatus()), + K3bJob::ERROR ); + + if( p->exitStatus() >= 254 && m_writingMode == K3b::DAO ) { + emit infoMessage( i18n("Sometimes using TAO writing mode solves this issue."), ERROR ); + } + else { + emit infoMessage( i18n("If you are running an unpatched cdrecord version..."), ERROR ); + emit infoMessage( i18n("...and this error also occurs with high quality media..."), ERROR ); + emit infoMessage( i18n("...and the K3b FAQ does not help you..."), ERROR ); + emit infoMessage( i18n("...please include the debugging output in your problem report."), ERROR ); + } + } + break; + } + jobFinished( false ); + } + } + else { + emit infoMessage( i18n("%1 did not exit cleanly.").arg(m_cdrecordBinObject->name()), + ERROR ); + jobFinished( false ); + } +} + + +void K3bCdrecordWriter::slotThroughput( int t ) +{ + emit writeSpeed( t, d->tracks[m_currentTrack-1].audio ? 175 : 150 ); +} + +#include "k3bcdrecordwriter.moc" diff --git a/libk3b/projects/k3bcdrecordwriter.h b/libk3b/projects/k3bcdrecordwriter.h new file mode 100644 index 0000000..9333588 --- /dev/null +++ b/libk3b/projects/k3bcdrecordwriter.h @@ -0,0 +1,123 @@ +/* + * + * $Id: k3bcdrecordwriter.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3B_CDRECORD_WRITER_H +#define K3B_CDRECORD_WRITER_H + + +#include "k3babstractwriter.h" + +#include + +class K3bExternalBin; +class K3bProcess; +class KProcess; +class K3bDevice::Device; + + +class K3bCdrecordWriter : public K3bAbstractWriter +{ + Q_OBJECT + + public: + K3bCdrecordWriter( K3bDevice::Device*, K3bJobHandler* hdl, + QObject* parent = 0, const char* name = 0 ); + ~K3bCdrecordWriter(); + + bool active() const; + + /** + * to be used in chain: addArgument(x)->addArgument(y) + */ + K3bCdrecordWriter* addArgument( const QString& ); + void clearArguments(); + + int fd() const; + + public slots: + void start(); + void cancel(); + + void setDao( bool b ); + void setWritingMode( int ); + void setCueFile( const QString& s); + void setClone( bool b ); + + void setRawCdText( const QByteArray& a ) { m_rawCdText = a; } + + /** + * If set true the job ignores the global K3b setting + * and does not eject the CD-RW after finishing + */ + void setForceNoEject( bool b ) { m_forceNoEject = b; } + + protected slots: + void slotStdLine( const QString& line ); + void slotProcessExited(KProcess*); + void slotThroughput( int t ); + + protected: + virtual void prepareProcess(); + + const K3bExternalBin* m_cdrecordBinObject; + K3bProcess* m_process; + + int m_writingMode; + bool m_totalTracksParsed; + bool m_clone; + bool m_cue; + + QString m_cueFile; + + enum CdrecordError { UNKNOWN, + OVERSIZE, + BAD_OPTION, + SHMGET_FAILED, + OPC_FAILED, + CANNOT_SET_SPEED, + CANNOT_SEND_CUE_SHEET, + CANNOT_OPEN_NEW_SESSION, + CANNOT_FIXATE_DISK, + WRITE_ERROR, + PERMISSION_DENIED, + BUFFER_UNDERRUN, + HIGH_SPEED_MEDIUM, + LOW_SPEED_MEDIUM, + MEDIUM_ERROR, + DEVICE_BUSY, + BLANK_FAILED }; + + QStringList m_arguments; + + private: + unsigned int m_currentTrack; + int m_totalTracks; + int m_totalSize; + int m_alreadyWritten; + + int m_lastFifoValue; + + int m_cdrecordError; + + bool m_forceNoEject; + + QByteArray m_rawCdText; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/k3bcuefileparser.cpp b/libk3b/projects/k3bcuefileparser.cpp new file mode 100644 index 0000000..49ca4fc --- /dev/null +++ b/libk3b/projects/k3bcuefileparser.cpp @@ -0,0 +1,461 @@ +/* + * + * $Id: k3bcuefileparser.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bcuefileparser.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + +// avoid usage of QTextStream since K3b often +// tries to open big files (iso images) in a +// cue file parser to test it. +static QString readLine( QFile* f ) +{ + QString s; + Q_LONG r = f->readLine( s, 1024 ); + if( r >= 0 ) { + // remove the trailing newline + return s.stripWhiteSpace(); + } + else { + // end of file or error + return QString::null; + } +} + + +// TODO: add method: usableByCdrecordDirectly() +// TODO: add Toc with sector sizes + +class K3bCueFileParser::Private +{ +public: + bool inFile; + bool inTrack; + int trackType; + int trackMode; + bool rawData; + bool haveIndex1; + K3b::Msf currentDataPos; + K3b::Msf index0; + + K3bDevice::Toc toc; + int currentParsedTrack; + + K3bDevice::CdText cdText; +}; + + + +K3bCueFileParser::K3bCueFileParser( const QString& filename ) + : K3bImageFileReader() +{ + d = new Private; + openFile( filename ); +} + + +K3bCueFileParser::~K3bCueFileParser() +{ + delete d; +} + + +void K3bCueFileParser::readFile() +{ + setValid(true); + + d->inFile = d->inTrack = d->haveIndex1 = false; + d->trackMode = K3bDevice::Track::UNKNOWN; + d->toc.clear(); + d->cdText.clear(); + d->currentParsedTrack = 0; + + QFile f( filename() ); + if( f.open( IO_ReadOnly ) ) { + QString line = readLine( &f ); + while( !line.isNull() ) { + + if( !parseLine(line) ) { + setValid(false); + break; + } + + line = readLine( &f ); + } + + if( isValid() ) { + // save last parsed track for which we do not have the proper length :( + if( d->currentParsedTrack > 0 ) { + d->toc.append( K3bDevice::Track( d->currentDataPos, + d->currentDataPos, + d->trackType, + d->trackMode ) ); + } + + // debug the toc + kdDebug() << "(K3bCueFileParser) successfully parsed cue file." << endl + << "------------------------------------------------" << endl; + for( unsigned int i = 0; i < d->toc.count(); ++i ) { + K3bDevice::Track& track = d->toc[i]; + kdDebug() << "Track " << (i+1) + << " (" << ( track.type() == K3bDevice::Track::AUDIO ? "audio" : "data" ) << ") " + << track.firstSector().toString() << " - " << track.lastSector().toString() << endl; + } + + kdDebug() << "------------------------------------------------" << endl; + } + } + else { + kdDebug() << "(K3bCueFileParser) could not open file " << filename() << endl; + setValid(false); + } +} + + +bool K3bCueFileParser::parseLine( QString& line ) +{ + // use cap(1) for the filename + static QRegExp fileRx( "FILE\\s\"?([^\"]*)\"?\\s[^\"\\s]*" ); + + // use cap(1) for the flags + static QRegExp flagsRx( "FLAGS(\\s(DCP|4CH|PRE|SCMS)){1,4}" ); + + // use cap(1) for the tracknumber and cap(2) for the datatype + static QRegExp trackRx( "TRACK\\s(\\d{1,2})\\s(AUDIO|CDG|MODE1/2048|MODE1/2352|MODE2/2336|MODE2/2352|CDI/2336|CDI/2352)" ); + + // use cap(1) for the index number, cap(3) for the minutes, cap(4) for the seconds, cap(5) for the frames, + // and cap(2) for the MSF value string + static QRegExp indexRx( "INDEX\\s(\\d{1,2})\\s((\\d+):([0-5]\\d):((?:[0-6]\\d)|(?:7[0-4])))" ); + + // use cap(1) for the MCN + static QRegExp catalogRx( "CATALOG\\s(\\w{13,13})" ); + + // use cap(1) for the ISRC + static QRegExp isrcRx( "ISRC\\s(\\w{5,5}\\d{7,7})" ); + + static QString cdTextRxStr = "\"?([^\"]{0,80})\"?"; + + // use cap(1) for the string + static QRegExp titleRx( "TITLE\\s" + cdTextRxStr ); + static QRegExp performerRx( "PERFORMER\\s" + cdTextRxStr ); + static QRegExp songwriterRx( "SONGWRITER\\s" + cdTextRxStr ); + + + // simplify all white spaces except those in filenames and CD-TEXT + simplifyWhiteSpace( line ); + + // skip comments and empty lines + if( line.startsWith("REM") || line.startsWith("#") || line.isEmpty() ) + return true; + + + // + // FILE + // + if( fileRx.exactMatch( line ) ) { + + setValid( findImageFileName( fileRx.cap(1) ) ); + + if( d->inFile ) { + kdDebug() << "(K3bCueFileParser) only one FILE statement allowed." << endl; + return false; + } + d->inFile = true; + d->inTrack = false; + d->haveIndex1 = false; + return true; + } + + + // + // TRACK + // + else if( trackRx.exactMatch( line ) ) { + if( !d->inFile ) { + kdDebug() << "(K3bCueFileParser) TRACK statement before FILE." << endl; + return false; + } + + // check if we had index1 for the last track + if( d->inTrack && !d->haveIndex1 ) { + kdDebug() << "(K3bCueFileParser) TRACK without INDEX 1." << endl; + return false; + } + + // save last track + // TODO: use d->rawData in some way + if( d->currentParsedTrack > 0 ) { + d->toc.append( K3bDevice::Track( d->currentDataPos, + d->currentDataPos, + d->trackType, + d->trackMode ) ); + } + + d->currentParsedTrack++; + + d->cdText.resize( d->currentParsedTrack ); + + // parse the tracktype + if( trackRx.cap(2) == "AUDIO" ) { + d->trackType = K3bDevice::Track::AUDIO; + d->trackMode = K3bDevice::Track::UNKNOWN; + } + else { + d->trackType = K3bDevice::Track::DATA; + if( trackRx.cap(2).startsWith("MODE1") ) { + d->trackMode = K3bDevice::Track::MODE1; + d->rawData = (trackRx.cap(2) == "MODE1/2352"); + } + else if( trackRx.cap(2).startsWith("MODE2") ) { + d->trackMode = K3bDevice::Track::MODE2; + d->rawData = (trackRx.cap(2) == "MODE2/2352"); + } + else { + kdDebug() << "(K3bCueFileParser) unsupported track type: " << trackRx.cap(2) << endl; + return false; + } + } + + d->haveIndex1 = false; + d->inTrack = true; + d->index0 = 0; + + return true; + } + + + // + // FLAGS + // + else if( flagsRx.exactMatch( line ) ) { + if( !d->inTrack ) { + kdDebug() << "(K3bCueFileParser) FLAGS statement without TRACK." << endl; + return false; + } + + // TODO: save the flags + return true; + } + + + // + // INDEX + // + else if( indexRx.exactMatch( line ) ) { + if( !d->inTrack ) { + kdDebug() << "(K3bCueFileParser) INDEX statement without TRACK." << endl; + return false; + } + + unsigned int indexNumber = indexRx.cap(1).toInt(); + + K3b::Msf indexStart = K3b::Msf::fromString( indexRx.cap(2) ); + + if( indexNumber == 0 ) { + d->index0 = indexStart; + + if( d->currentParsedTrack < 2 && indexStart > 0 ) { + kdDebug() << "(K3bCueFileParser) first track is not allowed to have a pregap > 0." << endl; + return false; + } + } + else if( indexNumber == 1 ) { + d->haveIndex1 = true; + d->currentDataPos = indexStart; + if( d->currentParsedTrack > 1 ) { + d->toc[d->currentParsedTrack-2].setLastSector( indexStart-1 ); + if( d->index0 > 0 && d->index0 < indexStart ) { + d->toc[d->currentParsedTrack-2].setIndex0( d->index0 - d->toc[d->currentParsedTrack-2].firstSector() ); + } + } + } + else { + // TODO: add index > 0 + } + + return true; + } + + + // + // CATALOG + // + if( catalogRx.exactMatch( line ) ) { + // TODO: set the toc's mcn + return true; + } + + + // + // ISRC + // + if( isrcRx.exactMatch( line ) ) { + if( d->inTrack ) { + // TODO: set the track's ISRC + return true; + } + else { + kdDebug() << "(K3bCueFileParser) ISRC without TRACK." << endl; + return false; + } + } + + + // + // CD-TEXT + // TODO: create K3bDevice::TrackCdText entries + // + else if( titleRx.exactMatch( line ) ) { + if( d->inTrack ) + d->cdText[d->currentParsedTrack-1].setTitle( titleRx.cap(1) ); + else + d->cdText.setTitle( titleRx.cap(1) ); + return true; + } + + else if( performerRx.exactMatch( line ) ) { + if( d->inTrack ) + d->cdText[d->currentParsedTrack-1].setPerformer( performerRx.cap(1) ); + else + d->cdText.setPerformer( performerRx.cap(1) ); + return true; + } + + else if( songwriterRx.exactMatch( line ) ) { + if( d->inTrack ) + d->cdText[d->currentParsedTrack-1].setSongwriter( songwriterRx.cap(1) ); + else + d->cdText.setSongwriter( songwriterRx.cap(1) ); + return true; + } + + else { + kdDebug() << "(K3bCueFileParser) unknown Cue line: '" << line << "'" << endl; + return false; + } +} + + +void K3bCueFileParser::simplifyWhiteSpace( QString& s ) +{ + s = s.stripWhiteSpace(); + + unsigned int i = 0; + bool insideQuote = false; + while( i < s.length() ) { + if( !insideQuote ) { + if( s[i].isSpace() && s[i+1].isSpace() ) + s.remove( i, 1 ); + } + + if( s[i] == '"' ) + insideQuote = !insideQuote; + + ++i; + } +} + + +const K3bDevice::Toc& K3bCueFileParser::toc() const +{ + return d->toc; +} + + +const K3bDevice::CdText& K3bCueFileParser::cdText() const +{ + return d->cdText; +} + + +bool K3bCueFileParser::findImageFileName( const QString& dataFile ) +{ + // + // CDRDAO does not use this image filename but replaces the extension from the cue file + // with "bin" to get the image filename, we should take this into account + // + + m_imageFilenameInCue = true; + + // first try filename as a hole (absolut) + if( QFile::exists( dataFile ) ) { + setImageFilename( QFileInfo(dataFile).absFilePath() ); + return true; + } + + // try the filename in the cue's directory + if( QFileInfo( K3b::parentDir(filename()) + dataFile.section( '/', -1 ) ).isFile() ) { + setImageFilename( K3b::parentDir(filename()) + dataFile.section( '/', -1 ) ); + kdDebug() << "(K3bCueFileParser) found image file: " << imageFilename() << endl; + return true; + } + + // try the filename ignoring case + if( QFileInfo( K3b::parentDir(filename()) + dataFile.section( '/', -1 ).lower() ).isFile() ) { + setImageFilename( K3b::parentDir(filename()) + dataFile.section( '/', -1 ).lower() ); + kdDebug() << "(K3bCueFileParser) found image file: " << imageFilename() << endl; + return true; + } + + m_imageFilenameInCue = false; + + // try removing the ending from the cue file (image.bin.cue and image.bin) + if( QFileInfo( filename().left( filename().length()-4 ) ).isFile() ) { + setImageFilename( filename().left( filename().length()-4 ) ); + kdDebug() << "(K3bCueFileParser) found image file: " << imageFilename() << endl; + return true; + } + + // + // we did not find the image specified in the cue. + // Search for another one having the same filename as the cue but a different extension + // + + QDir parentDir( K3b::parentDir(filename()) ); + QString filenamePrefix = filename().section( '/', -1 ); + filenamePrefix.truncate( filenamePrefix.length() - 3 ); // remove cue extension + kdDebug() << "(K3bCueFileParser) checking folder " << parentDir.path() << " for files: " << filenamePrefix << "*" << endl; + + // + // we cannot use the nameFilter in QDir because of the spaces that may occur in filenames + // + QStringList possibleImageFiles = parentDir.entryList( QDir::Files ); + int cnt = 0; + for( QStringList::const_iterator it = possibleImageFiles.constBegin(); it != possibleImageFiles.constEnd(); ++it ) { + if( (*it).lower() == dataFile.section( '/', -1 ).lower() || + (*it).startsWith( filenamePrefix ) && !(*it).endsWith( "cue" ) ) { + ++cnt; + setImageFilename( K3b::parentDir(filename()) + *it ); + } + } + + // + // we only do this if there is one unique file which fits the requirements. + // Otherwise we cannot be certain to have the right file. + // + return ( cnt == 1 && QFileInfo( imageFilename() ).isFile() ); +} diff --git a/libk3b/projects/k3bcuefileparser.h b/libk3b/projects/k3bcuefileparser.h new file mode 100644 index 0000000..41a5ee6 --- /dev/null +++ b/libk3b/projects/k3bcuefileparser.h @@ -0,0 +1,57 @@ +/* + * + * $Id: k3bcuefileparser.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_CUEFILE_PARSER_H_ +#define _K3B_CUEFILE_PARSER_H_ + +#include "k3bimagefilereader.h" + +#include +#include +#include "k3b_export.h" +/** + * Parses a cue file. + * Datatracks have either mode1 or mode2 where the latter contains xa form1/2. + * The last track may not have a proper length! + */ +class LIBK3B_EXPORT K3bCueFileParser : public K3bImageFileReader +{ + public: + K3bCueFileParser( const QString& filename = QString::null ); + ~K3bCueFileParser(); + + /** + * CDRDAO does not use this image filename but replaces the extension from the cue file + * with "bin" to get the image filename. + * So in this case cdrecord won't be able to burn the cue file. That is why we need this hack. + */ + bool imageFilenameInCue() const { return m_imageFilenameInCue; } + + const K3bDevice::Toc& toc() const; + const K3bDevice::CdText& cdText() const; + + private: + void readFile(); + bool parseLine( QString& line ); + void simplifyWhiteSpace( QString& s ); + bool findImageFileName( const QString& fileEntry ); + + bool m_imageFilenameInCue; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/k3bdoc.cpp b/libk3b/projects/k3bdoc.cpp new file mode 100644 index 0000000..ac5346d --- /dev/null +++ b/libk3b/projects/k3bdoc.cpp @@ -0,0 +1,221 @@ +/* + * + * $Id: k3bdoc.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +// include files for Qt +#include +#include +#include + +// include files for KDE +#include +#include + +// application specific includes +#include "k3bdoc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +K3bDoc::K3bDoc( QObject* parent ) + : QObject( parent ), + m_modified(false), + m_view(0) +{ + connect( this, SIGNAL(changed()), this, SLOT(slotChanged()) ); +} + + +K3bDoc::~K3bDoc() +{ +} + + +void K3bDoc::slotChanged() +{ + setModified( true ); + emit changed( this ); +} + + +void K3bDoc::setModified( bool m ) +{ + if( m != m_modified ) { + m_modified = m; + if( m ) + emit changed(); + } +} + + +void K3bDoc::setDummy( bool b ) +{ + m_dummy = b; +} + +void K3bDoc::setSpeed( int speed ) +{ + m_speed = speed; +} + +void K3bDoc::setBurner( K3bDevice::Device* dev ) +{ + m_burner = dev; +} + + +void K3bDoc::addUrl( const KURL& url ) +{ + KURL::List urls(url); + addUrls( urls ); +} + + +void K3bDoc::setURL( const KURL& url ) +{ + doc_url = url; + + emit changed(); +} + +const KURL& K3bDoc::URL() const +{ + return doc_url; +} + + +QString K3bDoc::name() const +{ + return URL().path().section( '/', -1 ); +} + + +bool K3bDoc::newDocument() +{ + setModified( false ); + + m_copies = 1; + m_burner = 0; + m_onTheFly = true; + m_speed = 0; // Auto + m_onlyCreateImages = false; + m_removeImages = true; + m_dummy = false; + m_writingApp = K3b::DEFAULT; + m_writingMode = K3b::WRITING_MODE_AUTO; + m_saved = false; + + return true; +} + + +bool K3bDoc::saveGeneralDocumentData( QDomElement* part ) +{ + QDomDocument doc = part->ownerDocument(); + QDomElement mainElem = doc.createElement( "general" ); + + QDomElement propElem = doc.createElement( "writing_mode" ); + switch( writingMode() ) { + case K3b::DAO: + propElem.appendChild( doc.createTextNode( "dao" ) ); + break; + case K3b::TAO: + propElem.appendChild( doc.createTextNode( "tao" ) ); + break; + case K3b::RAW: + propElem.appendChild( doc.createTextNode( "raw" ) ); + break; + default: + propElem.appendChild( doc.createTextNode( "auto" ) ); + break; + } + mainElem.appendChild( propElem ); + + propElem = doc.createElement( "dummy" ); + propElem.setAttribute( "activated", dummy() ? "yes" : "no" ); + mainElem.appendChild( propElem ); + + propElem = doc.createElement( "on_the_fly" ); + propElem.setAttribute( "activated", onTheFly() ? "yes" : "no" ); + mainElem.appendChild( propElem ); + + propElem = doc.createElement( "only_create_images" ); + propElem.setAttribute( "activated", onlyCreateImages() ? "yes" : "no" ); + mainElem.appendChild( propElem ); + + propElem = doc.createElement( "remove_images" ); + propElem.setAttribute( "activated", removeImages() ? "yes" : "no" ); + mainElem.appendChild( propElem ); + + part->appendChild( mainElem ); + + return true; +} + + +bool K3bDoc::readGeneralDocumentData( const QDomElement& elem ) +{ + if( elem.nodeName() != "general" ) + return false; + + QDomNodeList nodes = elem.childNodes(); + for( uint i = 0; i < nodes.count(); i++ ) { + + QDomElement e = nodes.item(i).toElement(); + if( e.isNull() ) + return false; + + if( e.nodeName() == "writing_mode") { + QString mode = e.text(); + if( mode == "dao" ) + setWritingMode( K3b::DAO ); + else if( mode == "tao" ) + setWritingMode( K3b::TAO ); + else if( mode == "raw" ) + setWritingMode( K3b::RAW ); + else + setWritingMode( K3b::WRITING_MODE_AUTO ); + } + + if( e.nodeName() == "dummy") + setDummy( e.attributeNode( "activated" ).value() == "yes" ); + + if( e.nodeName() == "on_the_fly") + setOnTheFly( e.attributeNode( "activated" ).value() == "yes" ); + + if( e.nodeName() == "only_create_images") + setOnlyCreateImages( e.attributeNode( "activated" ).value() == "yes" ); + + if( e.nodeName() == "remove_images") + setRemoveImages( e.attributeNode( "activated" ).value() == "yes" ); + } + + + return true; +} + + +#include "k3bdoc.moc" diff --git a/libk3b/projects/k3bdoc.h b/libk3b/projects/k3bdoc.h new file mode 100644 index 0000000..f241487 --- /dev/null +++ b/libk3b/projects/k3bdoc.h @@ -0,0 +1,229 @@ +/* + * + * $Id: k3bdoc.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BDOC_H +#define K3BDOC_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +// include files for QT +#include +#include +#include + + +// include files for KDE +#include +#include +#include "k3b_export.h" + +// forward declaration of the K3b classes +class QTimer; +class KTempFile; +class K3bBurnJob; +class QDomDocument; +class QDomElement; +class KConfig; +class KActionCollection; +class K3bJobHandler; + + +namespace K3bDevice { + class Device; +} +namespace K3b { + class Msf; +} + +/** + * K3bDoc is the base document class. + * It handles some general settings. + */ +class LIBK3B_EXPORT K3bDoc : public QObject +{ + Q_OBJECT + + public: + K3bDoc( QObject* = 0 ); + virtual ~K3bDoc(); + + enum DocType { + AUDIO = 1, + DATA, + MIXED, + VCD, + MOVIX, + MOVIX_DVD, + DVD, + VIDEODVD + }; + + virtual int type() const { return m_docType; } + + /** + * \return A name for the project which might for example be used as a suggestion for a file name + * when saving. The default implementation extracts a name from the URL. + */ + virtual QString name() const; + + /** + * \return A string representation of the document type. + */ + virtual QString typeString() const = 0; + + /** + * returns the view widget set with setView() or null if none has been set. + */ + QWidget* view() const { return m_view; } + + /** + * Just for convenience to make an easy mapping from doc to GUI possible. + */ + void setView( QWidget* v ) { m_view = v; } + + /** + * sets the modified flag for the document after a modifying action on the view connected to the document. + */ + virtual void setModified( bool m = true ); + + /** + * returns if the document is modified or not. Use this to determine + * if your document needs saving by the user on closing. + */ + virtual bool isModified() const { return m_modified; } + + /** + * Subclasses should call this when reimplementing. + * Sets some defaults. + */ + virtual bool newDocument(); + + /** + * Load a project from an xml stream. + * + * This is used to load/save k3b projects. + */ + virtual bool loadDocumentData( QDomElement* root ) = 0; + + /** + * Save a project to an xml stream. + * + * This is used to load/save k3b projects. + */ + virtual bool saveDocumentData( QDomElement* docElem ) = 0; + + /** returns the KURL of the document */ + const KURL& URL() const; + /** sets the URL of the document */ + virtual void setURL( const KURL& url ); + + int writingMode() const { return m_writingMode; } + bool dummy() const { return m_dummy; } + bool onTheFly() const { return m_onTheFly; } + bool removeImages() const { return m_removeImages; } + bool onlyCreateImages() const { return m_onlyCreateImages; } + int copies() const { return m_copies; } + int speed() const { return m_speed; } + K3bDevice::Device* burner() const { return m_burner; } + virtual KIO::filesize_t size() const = 0; + virtual K3b::Msf length() const = 0; + + // FIXME: rename this to something like imagePath + const QString& tempDir() const { return m_tempDir; } + + virtual int numOfTracks() const { return 1; } + + /** + * Create a new BurnJob to burn this project. It is not mandatory to use this + * method. You may also just create the BurnJob you need manually. It is just + * easier this way since you don't need to distinguish between the different + * project types. + */ + virtual K3bBurnJob* newBurnJob( K3bJobHandler*, QObject* parent = 0 ) = 0; + + int writingApp() const { return m_writingApp; } + void setWritingApp( int a ) { m_writingApp = a; } + + /** + * @return true if the document has successfully been saved to a file + */ + bool isSaved() const { return m_saved; } + + /** + * Used for session management. Use with care. + */ + void setSaved( bool s ) { m_saved = s; } + + signals: + void changed(); + void changed( K3bDoc* ); + + public slots: + void setDummy( bool d ); + void setWritingMode( int m ) { m_writingMode = m; } + void setOnTheFly( bool b ) { m_onTheFly = b; } + void setSpeed( int speed ); + void setBurner( K3bDevice::Device* dev ); + void setTempDir( const QString& dir ) { m_tempDir = dir; } + void setRemoveImages( bool b ) { m_removeImages = b; } + void setOnlyCreateImages( bool b ) { m_onlyCreateImages = b; } + void setCopies( int c ) { m_copies = c; } + + /** + * the default implementation just calls addUrls with + * list containing the url + */ + virtual void addUrl( const KURL& url ); + virtual void addUrls( const KURL::List& urls ) = 0; + + protected: + int m_docType; + + bool saveGeneralDocumentData( QDomElement* ); + + bool readGeneralDocumentData( const QDomElement& ); + + private slots: + void slotChanged(); + + private: + /** the modified flag of the current document */ + bool m_modified; + KURL doc_url; + + QWidget* m_view; + + QString m_tempDir; + K3bDevice::Device* m_burner; + bool m_dummy; + bool m_onTheFly; + bool m_removeImages; + bool m_onlyCreateImages; + int m_speed; + + /** see k3bglobals.h */ + int m_writingApp; + + int m_writingMode; + + int m_copies; + + bool m_saved; +}; + +#endif // K3BDOC_H diff --git a/libk3b/projects/k3bdvdrecordwriter.cpp b/libk3b/projects/k3bdvdrecordwriter.cpp new file mode 100644 index 0000000..0910d4a --- /dev/null +++ b/libk3b/projects/k3bdvdrecordwriter.cpp @@ -0,0 +1,119 @@ +/* + * + * $Id: k3bdvdrecordwriter.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bdvdrecordwriter.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + + +K3bDvdrecordWriter::K3bDvdrecordWriter( K3bDevice::Device* dev, QObject* parent, const char* name ) + : K3bCdrecordWriter( dev, parent, name ) +{ +} + + +K3bDvdrecordWriter::~K3bDvdrecordWriter() +{ +} + +void K3bDvdrecordWriter::prepareProcess() +{ + if( m_process ) delete m_process; // kdelibs want this! + m_process = new K3bProcess(); + m_process->setRunPrivileged(true); + m_process->setSplitStdout(true); + connect( m_process, SIGNAL(stdoutLine(const QString&)), this, SLOT(slotStdLine(const QString&)) ); + connect( m_process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotStdLine(const QString&)) ); + connect( m_process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited(KProcess*)) ); + connect( m_process, SIGNAL(wroteStdin(KProcess*)), this, SIGNAL(dataWritten()) ); + +// if( k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "dvd-patch" ) ) +// m_cdrecordBinObject = k3bcore->externalBinManager()->binObject("cdrecord"); +// else + m_cdrecordBinObject = k3bcore->externalBinManager()->binObject("dvdrecord"); + + if( !m_cdrecordBinObject ) + return; + + *m_process << m_cdrecordBinObject->path; + + // display progress + *m_process << "-v"; + + if( m_cdrecordBinObject->hasFeature( "delay") ) + *m_process << "-delay" << "0"; + else if( m_cdrecordBinObject->hasFeature( "gracetime") ) + *m_process << "gracetime=2"; // 2 is the lowest allowed value (Joerg, why do you do this to us?) + + // Again we assume the device to be set! + *m_process << QString("dev=%1").arg(K3b::externalBinDeviceParameter(burnDevice(), m_cdrecordBinObject)); + *m_process << QString("speed=%1").arg(burnSpeed()); + + // DVDs are only written in DAO mode (and Packet, but we do not support that since it does not + // make much sense here) + *m_process << "-dao"; + setWritingMode( K3b::DAO ); // just to make sure the CdrecordWriter emits the correct messages + + if( simulate() ) + *m_process << "-dummy"; + + if( burnproof() ) { + if( burnDevice()->burnproof() ) { + // with cdrecord 1.11a02 burnproof was renamed to burnfree + // what about dvdrecord?? + if( m_cdrecordBinObject->version < K3bVersion( "1.11a02" ) ) + *m_process << "driveropts=burnproof"; + else + *m_process << "driveropts=burnfree"; + } + else + emit infoMessage( i18n("Writer does not support buffer underrun free recording (BURNPROOF)"), INFO ); + } + + if( k3bcore->globalSettings()->ejectMedia() ) + *m_process << "-eject"; + + bool manualBufferSize = k3bcore->globalSettings()->manualBufferSize(); + if( manualBufferSize ) { + *m_process << QString("fs=%1m").arg( k3bcore->globalSettings()->writingBuffer() ); + } + + bool overburn = k3bcore->globalSettings()->overburn(); + if( overburn ) + if( m_cdrecordBinObject->hasFeature("overburn") ) + *m_process << "-overburn"; + else + emit infoMessage( i18n("Cdrecord %1 does not support overburning.").arg(m_cdrecordBinObject->version), INFO ); + + // additional user parameters from config + const QStringList& params = m_cdrecordBinObject->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *m_process << *it; + + // add the user parameters + for( QStringList::const_iterator it = m_arguments.begin(); it != m_arguments.end(); ++it ) + *m_process << *it; +} + +#include "k3bdvdrecordwriter.moc" + diff --git a/libk3b/projects/k3bdvdrecordwriter.h b/libk3b/projects/k3bdvdrecordwriter.h new file mode 100644 index 0000000..f9dcf4a --- /dev/null +++ b/libk3b/projects/k3bdvdrecordwriter.h @@ -0,0 +1,40 @@ +/* + * + * $Id: k3bdvdrecordwriter.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_DVDRECORD_WRITER_H_ +#define _K3B_DVDRECORD_WRITER_H_ + +#include "k3bcdrecordwriter.h" + + +class K3bDevice::Device; + +/** + * Basically this is just a wrapper around K3bCdrecordWriter + * which uses another K3bExternalBin and ignores the writingMode setting. + */ +class K3bDvdrecordWriter : public K3bCdrecordWriter +{ + Q_OBJECT + + public: + K3bDvdrecordWriter( K3bDevice::Device*, QObject* parent = 0, const char* name = 0 ); + ~K3bDvdrecordWriter(); + + protected: + void prepareProcess(); +}; + +#endif diff --git a/libk3b/projects/k3bgrowisofshandler.cpp b/libk3b/projects/k3bgrowisofshandler.cpp new file mode 100644 index 0000000..0b582ce --- /dev/null +++ b/libk3b/projects/k3bgrowisofshandler.cpp @@ -0,0 +1,318 @@ +/* + * + * $Id: k3bgrowisofshandler.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bgrowisofshandler.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + + +class K3bGrowisofsHandler::Private +{ +public: + int lastBuffer; + int lastDeviceBuffer; +}; + + +K3bGrowisofsHandler::K3bGrowisofsHandler( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + d = new Private; + reset(); +} + + +K3bGrowisofsHandler::~K3bGrowisofsHandler() +{ + delete d; +} + + +void K3bGrowisofsHandler::reset( K3bDevice::Device* dev, bool dao ) +{ + m_device = dev; + m_error = ERROR_UNKNOWN; + m_dao = dao; + d->lastBuffer = 0; + d->lastDeviceBuffer = 0; +} + + +void K3bGrowisofsHandler::handleStart() +{ +// QTimer::singleShot( 2000, this, SLOT(slotCheckBufferStatus()) ); +} + + +void K3bGrowisofsHandler::handleLine( const QString& line ) +{ + int pos = 0; + + if( line.startsWith( ":-[" ) ) { + // Error + + if( line.contains( "ASC=30h" ) ) + m_error = ERROR_MEDIA; + + // :-[ PERFORM OPC failed with SK=3h/ASC=73h/ASCQ=03h + else if( line.startsWith( ":-[ PERFORM OPC failed" ) ) + emit infoMessage( i18n("OPC failed. Please try writing speed 1x."), K3bJob::ERROR ); + + // :-[ attempt -blank=full or re-run with -dvd-compat -dvd-compat to engage DAO ] + else if( !m_dao && + ( line.contains( "engage DAO" ) || line.contains( "media is not formatted or unsupported" ) ) ) + emit infoMessage( i18n("Please try again with writing mode DAO."), K3bJob::ERROR ); + + else if( line.startsWith( ":-[ Failed to change write speed" ) ) { + m_error = ERROR_SPEED_SET_FAILED; + } + } + else if( line.startsWith( ":-(" ) ) { + if( line.contains( "No space left on device" ) ) + m_error = ERROR_OVERSIZE; + + else if( line.contains( "blocks are free" ) && line.contains( "to be written" ) ) { + m_error = ERROR_OVERSIZE; + if( k3bcore->globalSettings()->overburn() ) + emit infoMessage( i18n("Trying to write more than the official disk capacity"), K3bJob::WARNING ); + } + + else if( line.startsWith( ":-( unable to anonymously mmap" ) ) { + m_error = ERROR_MEMLOCK; + } + + else if( line.startsWith( ":-( write failed" ) ) { + m_error = ERROR_WRITE_FAILED; + } + + else + emit infoMessage( line, K3bJob::ERROR ); + } + else if( line.startsWith( "PERFORM OPC" ) ) { + m_error = ERROR_OPC; + } + else if( line.contains( "flushing cache" ) ) { + // here is where we already should stop queriying the buffer fill + // since the device is only used there so far... + m_device = 0; + + emit flushingCache(); + emit newSubTask( i18n("Flushing Cache") ); + emit infoMessage( i18n("Flushing the cache may take some time."), K3bJob::INFO ); + } + + // FIXME: I think this starts with dev->blockDeviceName() so we could improve parsing with: + // if( line.startsWith( dev->blockDeviceName() ) ) { + // line = line.mid( dev->blockDeviceName().length() ); + // if( line.startsWith( "closing..... + + else if( line.contains( "closing track" ) ) { + emit newSubTask( i18n("Closing Track") ); + } + else if( line.contains( "closing disc" ) ) { + emit newSubTask( i18n("Closing Disk") ); + } + else if( line.contains( "closing session" ) ) { + emit newSubTask( i18n("Closing Session") ); + } + else if( line.contains( "updating RMA" ) ) { + emit newSubTask( i18n("Updating RMA") ); + emit infoMessage( i18n("Updating RMA") + "...", K3bJob::INFO ); + } + else if( line.contains( "closing session" ) ) { + emit newSubTask( i18n("Closing Session") ); + emit infoMessage( i18n("Closing Session") + "...", K3bJob::INFO ); + } + else if( line.contains( "writing lead-out" ) ) { + emit newSubTask( i18n("Writing Lead-out") ); + emit infoMessage( i18n("Writing the lead-out may take some time."), K3bJob::INFO ); + } + else if( line.contains( "Quick Grow" ) ) { + emit infoMessage( i18n("Removing reference to lead-out."), K3bJob::INFO ); + } + else if( line.contains( "copying volume descriptor" ) ) { + emit infoMessage( i18n("Modifying ISO9660 volume descriptor"), K3bJob::INFO ); + } + else if( line.contains( "FEATURE 21h is not on" ) ) { + if( !m_dao ) { + // FIXME: it's not only the writer. It may be the media: something like does not support it with this media + // da war was mit: wenn einmal formattiert, dann geht nur noch dao oder wenn einmal als overwrite + // formattiert, dann nur noch dao oder sowas + emit infoMessage( i18n("Writing mode Incremental Streaming not available"), K3bJob::WARNING ); + emit infoMessage( i18n("Engaging DAO"), K3bJob::WARNING ); + } + } + else if( ( pos = line.find( "Current Write Speed" ) ) > 0 ) { + // parse write speed + // /dev/sr0: "Current Write Speed" is 2.4x1385KBps + + pos += 24; + int endPos = line.find( 'x', pos+1 ); + bool ok = true; + double speed = line.mid( pos, endPos-pos ).toDouble(&ok); + if( ok ) + emit infoMessage( i18n("Writing speed: %1 KB/s (%2x)") + .arg((int)(speed*1385.0)) + .arg(KGlobal::locale()->formatNumber(speed)), K3bJob::INFO ); + else + kdDebug() << "(K3bGrowisofsHandler) parsing error: '" << line.mid( pos, endPos-pos ) << "'" << endl; + } + else if( (pos = line.find( "RBU" )) > 0 ) { + + // FIXME: use QRegExp + + // parse ring buffer fill for growisofs >= 6.0 + pos += 4; + int endPos = line.find( '%', pos+1 ); + bool ok = true; + double val = line.mid( pos, endPos-pos ).toDouble( &ok ); + if( ok ) { + int newBuffer = (int)(val+0.5); + if( newBuffer != d->lastBuffer ) { + d->lastBuffer = newBuffer; + emit buffer( newBuffer ); + } + + // device buffer for growisofs >= 7.0 + pos = line.find( "UBU", pos ); + endPos = line.find( '%', pos+5 ); + if( pos > 0 ) { + pos += 4; + val = line.mid( pos, endPos-pos ).toDouble( &ok ); + if( ok ) { + int newBuffer = (int)(val+0.5); + if( newBuffer != d->lastDeviceBuffer ) { + d->lastDeviceBuffer = newBuffer; + emit deviceBuffer( newBuffer ); + } + } + } + } + else + kdDebug() << "(K3bGrowisofsHandler) failed to parse ring buffer fill from '" << line.mid( pos, endPos-pos ) << "'" << endl; + } + + else { + kdDebug() << "(growisofs) " << line << endl; + } +} + + +void K3bGrowisofsHandler::handleExit( int exitCode ) +{ + switch( m_error ) { + case ERROR_MEDIA: + emit infoMessage( i18n("K3b detected a problem with the media."), K3bJob::ERROR ); + emit infoMessage( i18n("Please try another media brand, preferably one explicitly recommended by your writer's vendor."), K3bJob::ERROR ); + emit infoMessage( i18n("Report the problem if it persists anyway."), K3bJob::ERROR ); + break; + + case ERROR_OVERSIZE: + if( k3bcore->globalSettings()->overburn() ) + emit infoMessage( i18n("Data did not fit on disk."), K3bJob::ERROR ); + else + emit infoMessage( i18n("Data does not fit on disk."), K3bJob::ERROR ); + break; + + case ERROR_SPEED_SET_FAILED: + emit infoMessage( i18n("Unable to set writing speed."), K3bJob::ERROR ); + emit infoMessage( i18n("Please try again with the 'ignore speed' setting."), K3bJob::ERROR ); + break; + + case ERROR_OPC: + emit infoMessage( i18n("Optimum Power Calibration failed."), K3bJob::ERROR ); + emit infoMessage( i18n("Try adding '-use-the-force-luke=noopc' to the " + "growisofs user parameters in the K3b settings."), K3bJob::ERROR ); + break; + + case ERROR_MEMLOCK: + emit infoMessage( i18n("Unable to allocate software buffer."), K3bJob::ERROR ); + emit infoMessage( i18n("This error is caused by the low memorylocked resource limit."), K3bJob::ERROR ); + emit infoMessage( i18n("It can be solved by issuing the command 'ulimit -l unlimited'..."), K3bJob::ERROR ); + emit infoMessage( i18n("...or by lowering the used software buffer size in the advanced K3b settings."), K3bJob::ERROR ); + break; + + case ERROR_WRITE_FAILED: + emit infoMessage( i18n("Write error"), K3bJob::ERROR ); + break; + + default: + + // + // The growisofs error codes: + // + // 128 + errno: fatal error upon program startup + // errno : fatal error during recording + // + + if( exitCode > 128 ) { + // for now we just emit a message with the error + // in the future when I know more about what kinds of errors may occur + // we will enhance this + emit infoMessage( i18n("Fatal error at startup: %1").arg(strerror(exitCode-128)), + K3bJob::ERROR ); + } + else if( exitCode == 1 ) { + // Doku says: warning at exit + // Example: mkisofs error + // unable to reload + // So basically this is just for mkisofs failure since we do not let growisofs reload the media + emit infoMessage( i18n("Warning at exit: (1)"), K3bJob::ERROR ); + emit infoMessage( i18n("Most likely mkisofs failed in some way."), K3bJob::ERROR ); + } + else { + emit infoMessage( i18n("Fatal error during recording: %1").arg(strerror(exitCode)), + K3bJob::ERROR ); + } + } + + reset(); +} + + +void K3bGrowisofsHandler::slotCheckBufferStatus() +{ + connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::BUFFER_CAPACITY, m_device ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotCheckBufferStatusDone(K3bDevice::DeviceHandler*)) ); +} + + +void K3bGrowisofsHandler::slotCheckBufferStatusDone( K3bDevice::DeviceHandler* dh ) +{ + if( dh->success() && dh->bufferCapacity() > 0 ) { + emit deviceBuffer( 100 * (dh->bufferCapacity() - dh->availableBufferCapacity() ) / dh->bufferCapacity() ); + QTimer::singleShot( 500, this, SLOT(slotCheckBufferStatus()) ); + } + else { + kdDebug() << "(K3bGrowisofsHandler) stopping buffer check." << endl; + } +} + +#include "k3bgrowisofshandler.moc" diff --git a/libk3b/projects/k3bgrowisofshandler.h b/libk3b/projects/k3bgrowisofshandler.h new file mode 100644 index 0000000..42fcd2a --- /dev/null +++ b/libk3b/projects/k3bgrowisofshandler.h @@ -0,0 +1,87 @@ +/* + * + * $Id: k3bgrowisofshandler.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_GROWISOFS_HANDLER_H_ +#define _K3B_GROWISOFS_HANDLER_H_ + +#include + +namespace K3bDevice { + class Device; + class DeviceHandler; +} + + +/** + * This class handles the output parsing for growisofs + * We put it in an extra class since we have two classes + * using growisofs: the writer and the imager. + */ +class K3bGrowisofsHandler : public QObject +{ + Q_OBJECT + + public: + K3bGrowisofsHandler( QObject* parent = 0, const char* name = 0 ); + ~K3bGrowisofsHandler(); + + enum ErrorType { + ERROR_UNKNOWN, + ERROR_MEDIA, + ERROR_OVERSIZE, + ERROR_SPEED_SET_FAILED, + ERROR_OPC, + ERROR_MEMLOCK, + ERROR_WRITE_FAILED + }; + + int error() const { return m_error; } + + public slots: + /** + * This will basically reset the error type + * @param dao was growisofs called with DAO? + */ + void reset( K3bDevice::Device* = 0, bool dao = false ); + + void handleStart(); + void handleLine( const QString& ); + void handleExit( int exitCode ); + + signals: + void infoMessage( const QString&, int ); + void newSubTask( const QString& ); + void buffer( int ); + void deviceBuffer( int ); + + /** + * We need this to know when the writing finished to update the progress + */ + void flushingCache(); + + private slots: + void slotCheckBufferStatus(); + void slotCheckBufferStatusDone( K3bDevice::DeviceHandler* ); + + private: + class Private; + Private* d; + + int m_error; + bool m_dao; + K3bDevice::Device* m_device; +}; + +#endif diff --git a/libk3b/projects/k3bgrowisofswriter.cpp b/libk3b/projects/k3bgrowisofswriter.cpp new file mode 100644 index 0000000..3144547 --- /dev/null +++ b/libk3b/projects/k3bgrowisofswriter.cpp @@ -0,0 +1,630 @@ +/* + * + * $Id: k3bgrowisofswriter.cpp 731898 2007-11-02 08:22:18Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bgrowisofswriter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "k3bgrowisofshandler.h" +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + + +class K3bGrowisofsWriter::Private +{ +public: + Private() + : writingMode( 0 ), + closeDvd(false), + multiSession(false), + process( 0 ), + growisofsBin( 0 ), + trackSize(-1), + layerBreak(0), + usingRingBuffer(false), + ringBuffer(0), + forceNoEject( false ) { + } + + int writingMode; + bool closeDvd; + bool multiSession; + K3bProcess* process; + const K3bExternalBin* growisofsBin; + QString image; + + bool success; + bool canceled; + bool finished; + + QTime lastSpeedCalculationTime; + int lastSpeedCalculationBytes; + int lastProgress; + unsigned int lastProgressed; + double lastWritingSpeed; + + bool writingStarted; + + K3bThroughputEstimator* speedEst; + K3bGrowisofsHandler* gh; + + // used in DAO with growisofs >= 5.15 + long trackSize; + + long layerBreak; + + unsigned long long overallSizeFromOutput; + long long firstSizeFromOutput; + + QFile inputFile; + + bool usingRingBuffer; + K3bPipeBuffer* ringBuffer; + + QString multiSessionInfo; + + bool forceNoEject; +}; + + +K3bGrowisofsWriter::K3bGrowisofsWriter( K3bDevice::Device* dev, K3bJobHandler* hdl, + QObject* parent, const char* name ) + : K3bAbstractWriter( dev, hdl, parent, name ) +{ + d = new Private; + d->speedEst = new K3bThroughputEstimator( this ); + connect( d->speedEst, SIGNAL(throughput(int)), + this, SLOT(slotThroughput(int)) ); + + d->gh = new K3bGrowisofsHandler( this ); + connect( d->gh, SIGNAL(infoMessage(const QString&, int)), + this,SIGNAL(infoMessage(const QString&, int)) ); + connect( d->gh, SIGNAL(newSubTask(const QString&)), + this, SIGNAL(newSubTask(const QString&)) ); + connect( d->gh, SIGNAL(buffer(int)), + this, SIGNAL(buffer(int)) ); + connect( d->gh, SIGNAL(deviceBuffer(int)), + this, SIGNAL(deviceBuffer(int)) ); + connect( d->gh, SIGNAL(flushingCache()), + this, SLOT(slotFlushingCache()) ); +} + + +K3bGrowisofsWriter::~K3bGrowisofsWriter() +{ + delete d->process; + delete d; +} + + +bool K3bGrowisofsWriter::active() const +{ + return (d->process ? d->process->isRunning() : false); +} + + +int K3bGrowisofsWriter::fd() const +{ + if( d->process ) { + if( d->usingRingBuffer ) + return d->ringBuffer->inFd(); + else + return d->process->stdinFd(); + } + else + return -1; +} + + +bool K3bGrowisofsWriter::closeFd() +{ + return ( !::close( fd() ) ); +} + + +bool K3bGrowisofsWriter::prepareProcess() +{ + d->growisofsBin = k3bcore->externalBinManager()->binObject( "growisofs" ); + if( !d->growisofsBin ) { + emit infoMessage( i18n("Could not find %1 executable.").arg("growisofs"), ERROR ); + return false; + } + + if( d->growisofsBin->version < K3bVersion( 5, 10 ) ) { + emit infoMessage( i18n("Growisofs version %1 is too old. " + "K3b needs at least version 5.10.").arg(d->growisofsBin->version), + ERROR ); + return false; + } + + emit debuggingOutput( "Used versions", "growisofs: " + d->growisofsBin->version ); + + if( !d->growisofsBin->copyright.isEmpty() ) + emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3").arg("growisofs") + .arg(d->growisofsBin->version).arg(d->growisofsBin->copyright), INFO ); + + + // + // The growisofs bin is ready. Now we add the parameters + // + delete d->process; + d->process = new K3bProcess(); + d->process->setRunPrivileged(true); + // d->process->setPriority( KProcess::PrioHighest ); + d->process->setSplitStdout(true); + d->process->setRawStdin(true); + connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotReceivedStderr(const QString&)) ); + connect( d->process, SIGNAL(stdoutLine(const QString&)), this, SLOT(slotReceivedStderr(const QString&)) ); + connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited(KProcess*)) ); + + + // + // growisofs < 5.20 wants the tracksize to be a multiple of 16 (1 ECC block: 16*2048 bytes) + // we simply pad ourselves. + // + // But since the writer itself properly pads or writes a longer lead-out we don't really need + // to write zeros. We just tell growisofs to reserve a multiple of 16 blocks. + // This is only releveant in DAO mode anyway. + // + // FIXME: seems as we also need this for double layer writing. Better make it the default and + // actually write the pad bytes. The only possibility I see right now is to add a padding option + // to the pipebuffer. + int trackSizePadding = 0; + if( d->trackSize > 0 && d->growisofsBin->version < K3bVersion( 5, 20 ) ) { + if( d->trackSize % 16 ) { + trackSizePadding = (16 - d->trackSize%16); + kdDebug() << "(K3bGrowisofsWriter) need to pad " << trackSizePadding << " blocks." << endl; + } + } + + + *d->process << d->growisofsBin; + + // set this var to true to enable the ringbuffer + d->usingRingBuffer = ( d->growisofsBin->version < K3bVersion( 6, 0 ) ); + + QString s = burnDevice()->blockDeviceName() + "="; + if( d->usingRingBuffer || d->image.isEmpty() ) { + // we always read from stdin since the ringbuffer does the actual reading from the source + s += "/dev/fd/0"; + } + else + s += d->image; + + if( d->multiSession && !d->multiSessionInfo.isEmpty() ) + *d->process << "-C" << d->multiSessionInfo; + + if( d->multiSession ) + *d->process << "-M"; + else + *d->process << "-Z"; + *d->process << s; + + + if( !d->image.isEmpty() && d->usingRingBuffer ) { + d->inputFile.setName( d->image ); + d->trackSize = (K3b::filesize( d->image ) + 1024) / 2048; + if( !d->inputFile.open( IO_ReadOnly ) ) { + emit infoMessage( i18n("Could not open file %1.").arg(d->image), ERROR ); + return false; + } + } + + // now we use the force (luke ;) do not reload the dvd, K3b does that. + *d->process << "-use-the-force-luke=notray"; + + // we check for existing filesystems ourselves, so we always force the overwrite... + *d->process << "-use-the-force-luke=tty"; + + bool dvdCompat = d->closeDvd; + + // DL writing with forced layer break + if( d->layerBreak > 0 ) { + *d->process << "-use-the-force-luke=break:" + QString::number(d->layerBreak); + dvdCompat = true; + } + + // the tracksize parameter takes priority over the dao:tracksize parameter since growisofs 5.18 + else if( d->growisofsBin->version > K3bVersion( 5, 17 ) && d->trackSize > 0 ) + *d->process << "-use-the-force-luke=tracksize:" + QString::number(d->trackSize + trackSizePadding); + + if( simulate() ) + *d->process << "-use-the-force-luke=dummy"; + + if( d->writingMode == K3b::DAO ) { + dvdCompat = true; + if( d->growisofsBin->version >= K3bVersion( 5, 15 ) && d->trackSize > 0 ) + *d->process << "-use-the-force-luke=dao:" + QString::number(d->trackSize + trackSizePadding); + else + *d->process << "-use-the-force-luke=dao"; + d->gh->reset( burnDevice(), true ); + } + else + d->gh->reset( burnDevice(), false ); + + // + // Never use the -dvd-compat parameter with DVD+RW media + // because the only thing it does is creating problems. + // Normally this should be done in growisofs + // + int mediaType = burnDevice()->mediaType(); + if( dvdCompat && + mediaType != K3bDevice::MEDIA_DVD_PLUS_RW && + mediaType != K3bDevice::MEDIA_DVD_RW_OVWR ) + *d->process << "-dvd-compat"; + + // + // Some DVD writers do not allow changing the writing speed so we allow + // the user to ignore the speed setting + // + int speed = burnSpeed(); + if( speed >= 0 ) { + if( speed == 0 ) { + // try to determine the writeSpeed + // if it fails determineOptimalWriteSpeed() will return 0 and + // the choice is left to growisofs which means that the choice is + // really left to the drive since growisofs does not change the speed + // if no option is given + speed = burnDevice()->determineMaximalWriteSpeed(); + } + + // speed may be a float number. example: DVD+R(W): 2.4x + if( speed != 0 ) + *d->process << QString("-speed=%1").arg( speed%1385 > 0 + ? QString::number( (float)speed/1385.0, 'f', 1 ) + : QString::number( speed/1385 ) ); + } + + if( k3bcore->globalSettings()->overburn() ) + *d->process << "-overburn"; + + if( !d->usingRingBuffer && d->growisofsBin->version >= K3bVersion( 6, 0 ) ) { + bool manualBufferSize = k3bcore->globalSettings()->useManualBufferSize(); + int bufSize = ( manualBufferSize ? k3bcore->globalSettings()->bufferSize() : 32 ); + *d->process << QString("-use-the-force-luke=bufsize:%1m").arg(bufSize); + } + + // additional user parameters from config + const QStringList& params = d->growisofsBin->userParameters(); + for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *d->process << *it; + + emit debuggingOutput( "Burned media", K3bDevice::mediaTypeString(mediaType) ); + + return true; +} + + +void K3bGrowisofsWriter::start() +{ + jobStarted(); + + d->lastWritingSpeed = 0; + d->lastProgressed = 0; + d->lastProgress = 0; + d->firstSizeFromOutput = -1; + d->lastSpeedCalculationTime = QTime::currentTime(); + d->lastSpeedCalculationBytes = 0; + d->writingStarted = false; + d->canceled = false; + d->speedEst->reset(); + d->finished = false; + + if( !prepareProcess() ) { + jobFinished( false ); + } + else { + + kdDebug() << "***** " << d->growisofsBin->name() << " parameters:\n"; + const QValueList& args = d->process->args(); + QString s; + for( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << flush << endl; + emit debuggingOutput( d->growisofsBin->name() + " command:", s); + + + emit newSubTask( i18n("Preparing write process...") ); + + // FIXME: check the return value + if( K3b::isMounted( burnDevice() ) ) { + emit infoMessage( i18n("Unmounting medium"), INFO ); + K3b::unmount( burnDevice() ); + } + + // block the device (including certain checks) + k3bcore->blockDevice( burnDevice() ); + + // lock the device for good in this process since it will + // be opened in the growisofs process + burnDevice()->close(); + burnDevice()->usageLock(); + + if( !d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) { + // something went wrong when starting the program + // it "should" be the executable + kdDebug() << "(K3bGrowisofsWriter) could not start " << d->growisofsBin->path << endl; + emit infoMessage( i18n("Could not start %1.").arg(d->growisofsBin->name()), K3bJob::ERROR ); + jobFinished(false); + } + else { + if( simulate() ) { + emit newTask( i18n("Simulating") ); + emit infoMessage( i18n("Starting simulation..."), + K3bJob::INFO ); + } + else { + emit newTask( i18n("Writing") ); + emit infoMessage( i18n("Starting disc write..."), K3bJob::INFO ); + } + + d->gh->handleStart(); + + // create the ring buffer + if( d->usingRingBuffer ) { + if( !d->ringBuffer ) { + d->ringBuffer = new K3bPipeBuffer( this, this ); + connect( d->ringBuffer, SIGNAL(percent(int)), this, SIGNAL(buffer(int)) ); + connect( d->ringBuffer, SIGNAL(finished(bool)), this, SLOT(slotRingBufferFinished(bool)) ); + } + + d->ringBuffer->writeToFd( d->process->stdinFd() ); + bool manualBufferSize = k3bcore->globalSettings()->useManualBufferSize(); + int bufSize = ( manualBufferSize ? k3bcore->globalSettings()->bufferSize() : 20 ); + d->ringBuffer->setBufferSize( bufSize ); + + if( !d->image.isEmpty() ) + d->ringBuffer->readFromFd( d->inputFile.handle() ); + + d->ringBuffer->start(); + } + } + } +} + + +void K3bGrowisofsWriter::cancel() +{ + if( active() ) { + d->canceled = true; + closeFd(); + if( d->usingRingBuffer && d->ringBuffer ) + d->ringBuffer->cancel(); + d->process->kill(); + } +} + + +void K3bGrowisofsWriter::setWritingMode( int m ) +{ + d->writingMode = m; +} + + +void K3bGrowisofsWriter::setTrackSize( long size ) +{ + d->trackSize = size; +} + + +void K3bGrowisofsWriter::setLayerBreak( long lb ) +{ + d->layerBreak = lb; +} + + +void K3bGrowisofsWriter::setCloseDvd( bool b ) +{ + d->closeDvd = b; +} + + +void K3bGrowisofsWriter::setMultiSession( bool b ) +{ + d->multiSession = b; +} + + +void K3bGrowisofsWriter::setImageToWrite( const QString& filename ) +{ + d->image = filename; +} + + +void K3bGrowisofsWriter::slotReceivedStderr( const QString& line ) +{ + emit debuggingOutput( d->growisofsBin->name(), line ); + + if( line.contains( "remaining" ) ) { + + if( !d->writingStarted ) { + d->writingStarted = true; + emit newSubTask( i18n("Writing data") ); + } + + // parse progress + int pos = line.find( "/" ); + unsigned long long done = line.left( pos ).toULongLong(); + bool ok = true; + d->overallSizeFromOutput = line.mid( pos+1, line.find( "(", pos ) - pos - 1 ).toULongLong( &ok ); + if( d->firstSizeFromOutput == -1 ) + d->firstSizeFromOutput = done; + done -= d->firstSizeFromOutput; + d->overallSizeFromOutput -= d->firstSizeFromOutput; + if( ok ) { + int p = (int)(100 * done / d->overallSizeFromOutput); + if( p > d->lastProgress ) { + emit percent( p ); + emit subPercent( p ); + d->lastProgress = p; + } + if( (unsigned int)(done/1024/1024) > d->lastProgressed ) { + d->lastProgressed = (unsigned int)(done/1024/1024); + emit processedSize( d->lastProgressed, (int)(d->overallSizeFromOutput/1024/1024) ); + emit processedSubSize( d->lastProgressed, (int)(d->overallSizeFromOutput/1024/1024) ); + } + + // try parsing write speed (since growisofs 5.11) + pos = line.find( '@' ); + if( pos != -1 ) { + pos += 1; + double speed = line.mid( pos, line.find( 'x', pos ) - pos ).toDouble(&ok); + if( ok ) { + if( d->lastWritingSpeed != speed ) + emit writeSpeed( (int)(speed*1385.0), 1385 ); + d->lastWritingSpeed = speed; + } + else + kdDebug() << "(K3bGrowisofsWriter) speed parsing failed: '" + << line.mid( pos, line.find( 'x', pos ) - pos ) << "'" << endl; + } + else { + d->speedEst->dataWritten( done/1024 ); + } + } + else + kdDebug() << "(K3bGrowisofsWriter) progress parsing failed: '" + << line.mid( pos+1, line.find( "(", pos ) - pos - 1 ).stripWhiteSpace() << "'" << endl; + } + + // else + // to be able to parse the ring buffer fill in growisofs 6.0 we need to do this all the time + // FIXME: get rid of the K3bGrowisofsHandler once it is sure that we do not need the K3bGrowisofsImager anymore + d->gh->handleLine( line ); +} + + +void K3bGrowisofsWriter::slotProcessExited( KProcess* p ) +{ + d->inputFile.close(); + + // release the device within this process + burnDevice()->usageUnlock(); + + // unblock the device + k3bcore->unblockDevice( burnDevice() ); + + if( d->canceled ) { + if( !d->finished ) { + d->finished = true; + // this will unblock and eject the drive and emit the finished/canceled signals + K3bAbstractWriter::cancel(); + } + return; + } + + d->finished = true; + + // it seems that growisofs sometimes exits with a valid exit code while a write error occured + if( p->exitStatus() == 0 && d->gh->error() != K3bGrowisofsHandler::ERROR_WRITE_FAILED ) { + + int s = d->speedEst->average(); + if( s > 0 ) + emit infoMessage( i18n("Average overall write speed: %1 KB/s (%2x)") + .arg(s).arg(KGlobal::locale()->formatNumber((double)s/1385.0), 2), INFO ); + + if( simulate() ) + emit infoMessage( i18n("Simulation successfully completed"), K3bJob::SUCCESS ); + else + emit infoMessage( i18n("Writing successfully completed"), K3bJob::SUCCESS ); + + d->success = true; + } + else { + if( !wasSourceUnreadable() ) + d->gh->handleExit( p->exitStatus() ); + d->success = false; + } + + if( !k3bcore->globalSettings()->ejectMedia() || d->forceNoEject ) + jobFinished(d->success); + else { + emit newSubTask( i18n("Ejecting DVD") ); + connect( K3bDevice::eject( burnDevice() ), + SIGNAL(finished(K3bDevice::DeviceHandler*)), + this, + SLOT(slotEjectingFinished(K3bDevice::DeviceHandler*)) ); + } +} + + +void K3bGrowisofsWriter::slotRingBufferFinished( bool ) +{ + if( !d->finished ) { + d->finished = true; + // this will unblock and eject the drive and emit the finished/canceled signals + K3bAbstractWriter::cancel(); + } +} + + +void K3bGrowisofsWriter::slotEjectingFinished( K3bDevice::DeviceHandler* dh ) +{ + if( !dh->success() ) + emit infoMessage( i18n("Unable to eject media."), ERROR ); + + jobFinished(d->success); +} + + +void K3bGrowisofsWriter::slotThroughput( int t ) +{ + emit writeSpeed( t, 1385 ); +} + + +void K3bGrowisofsWriter::slotFlushingCache() +{ + if( !d->canceled ) { + // + // growisofs's progress output stops before 100%, so we do it manually + // + emit percent( 100 ); + emit processedSize( d->overallSizeFromOutput/1024/1024, + d->overallSizeFromOutput/1024/1024 ); + } +} + + +void K3bGrowisofsWriter::setMultiSessionInfo( const QString& info ) +{ + d->multiSessionInfo = info; +} + + +void K3bGrowisofsWriter::setForceNoEject( bool b ) +{ + d->forceNoEject = b; +} + +#include "k3bgrowisofswriter.moc" diff --git a/libk3b/projects/k3bgrowisofswriter.h b/libk3b/projects/k3bgrowisofswriter.h new file mode 100644 index 0000000..ed69923 --- /dev/null +++ b/libk3b/projects/k3bgrowisofswriter.h @@ -0,0 +1,106 @@ +/* + * + * $Id: k3bgrowisofswriter.h 679276 2007-06-23 13:25:21Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_GROWISOFS_WRITER_H_ +#define _K3B_GROWISOFS_WRITER_H_ + +#include "k3babstractwriter.h" + + +namespace K3bDevice { + class Device; + class DeviceHandler; +} +class KProcess; + + + +class K3bGrowisofsWriter : public K3bAbstractWriter +{ + Q_OBJECT + + public: + K3bGrowisofsWriter( K3bDevice::Device*, K3bJobHandler*, + QObject* parent = 0, const char* name = 0 ); + ~K3bGrowisofsWriter(); + + bool active() const; + + int fd() const; + bool closeFd(); + + public slots: + void start(); + void cancel(); + + void setWritingMode( int ); + + /** + * If true the growisofs parameter -M is used in favor of -Z. + */ + void setMultiSession( bool b ); + + /** + * Only used in DAO mode and only supported with growisofs >= 5.15 + * @param size size in blocks + */ + void setTrackSize( long size ); + + /** + * Use this in combination with setTrackSize when writing double layer media. + * @param lb The number of data sectors in the first layer. It needs to be less or equal + * to tracksize/2. The writer will pad the second layer with zeros if + * break < tracksize/2. + * If set to 0 this setting will be ignored. + */ + void setLayerBreak( long lb ); + + /** + * Close the DVD to enable max DVD compatibility (uses the growisofs --dvd-compat parameter) + * This will also be used in DAO mode and when the layerBreak has been set. + */ + void setCloseDvd( bool ); + + /** + * set this to QString::null or an empty string to let the writer + * read it's data from fd() + */ + void setImageToWrite( const QString& ); + + /** + * While reading the image from stdin growisofs needs + * a valid -C parameter for multisession. + */ + void setMultiSessionInfo( const QString& ); + + void setForceNoEject( bool ); + + protected: + bool prepareProcess(); + + protected slots: + void slotReceivedStderr( const QString& ); + void slotProcessExited( KProcess* ); + void slotEjectingFinished( K3bDevice::DeviceHandler* dh ); + void slotThroughput( int t ); + void slotFlushingCache(); + void slotRingBufferFinished( bool ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/k3bimagefilereader.cpp b/libk3b/projects/k3bimagefilereader.cpp new file mode 100644 index 0000000..70ece16 --- /dev/null +++ b/libk3b/projects/k3bimagefilereader.cpp @@ -0,0 +1,88 @@ +/* + * + * $Id: k3bimagefilereader.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bimagefilereader.h" + +#include +#include + +#include + + + +class K3bImageFileReader::Private +{ +public: + Private() + : isValid(false) { + } + + QString filename; + QString imageFilename; + bool isValid; +}; + + +K3bImageFileReader::K3bImageFileReader() +{ + d = new Private(); +} + + +K3bImageFileReader::~K3bImageFileReader() +{ + delete d; +} + + +void K3bImageFileReader::openFile( const QString& filename ) +{ + d->filename = filename; + d->imageFilename = QString::null; + setValid(false); + + if( !filename.isEmpty() ) + readFile(); +} + + +void K3bImageFileReader::setValid( bool b ) +{ + d->isValid = b; +} + + +void K3bImageFileReader::setImageFilename( const QString& filename ) +{ + d->imageFilename = filename; +} + + +bool K3bImageFileReader::isValid() const +{ + return d->isValid; +} + + +const QString& K3bImageFileReader::filename() const +{ + return d->filename; +} + + +const QString& K3bImageFileReader::imageFilename() const +{ + return d->imageFilename; +} diff --git a/libk3b/projects/k3bimagefilereader.h b/libk3b/projects/k3bimagefilereader.h new file mode 100644 index 0000000..2bf727e --- /dev/null +++ b/libk3b/projects/k3bimagefilereader.h @@ -0,0 +1,55 @@ +/* + * + * $Id: k3bimagefilereader.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_IMAGE_FILE_READER_H_ +#define _K3B_IMAGE_FILE_READER_H_ + +#include +#include "k3b_export.h" + +class LIBK3B_EXPORT K3bImageFileReader +{ + public: + K3bImageFileReader(); + virtual ~K3bImageFileReader(); + + /** + * Open a file. In most cases the TOC file + */ + void openFile( const QString& filename ); + + virtual bool isValid() const; + + /** + * Return the current set filename; + */ + const QString& filename() const; + + /** + * returns the name of the corresponding image file. + */ + virtual const QString& imageFilename() const; + + protected: + virtual void readFile() = 0; + void setValid( bool ); + void setImageFilename( const QString& ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/k3binffilewriter.cpp b/libk3b/projects/k3binffilewriter.cpp new file mode 100644 index 0000000..9395b2a --- /dev/null +++ b/libk3b/projects/k3binffilewriter.cpp @@ -0,0 +1,186 @@ +/* + * + * $Id: k3binffilewriter.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3binffilewriter.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + + + +K3bInfFileWriter::K3bInfFileWriter() + : m_index0(-1), + m_trackNumber(1), + m_trackStart(0), + m_trackLength(0), + m_preEmphasis(false), + m_copyPermitted(true), + m_bigEndian(false) +{ +} + + +bool K3bInfFileWriter::save( const QString& filename ) +{ + QFile f( filename ); + + if( !f.open( IO_WriteOnly ) ) { + kdDebug() << "(K3bInfFileWriter) could not open file " << f.name() << endl; + return false; + } + + QTextStream s( &f ); + + return save( s ); +} + + +bool K3bInfFileWriter::save( QTextStream& s ) +{ + // now write the inf data + // ---------------------- + // header + s << "# Cdrecord-Inf-File written by K3b " << k3bcore->version() + << ", " << QDateTime::currentDateTime().toString() << endl + << "#" << endl; + + s << "ISRC=\t\t" << m_isrc << endl; + s << "MCN=\t\t" << m_mcn << endl; + + // CD-Text + s << "Albumperformer=\t" << "'" << m_albumPerformer << "'" << endl; + s << "Albumtitle=\t" << "'" << m_albumTitle << "'" << endl; + + s << "Performer=\t" << "'" << m_trackPerformer << "'" << endl; + s << "Songwriter=\t" << "'" << m_trackSongwriter << "'" << endl; + s << "Composer=\t" << "'" << m_trackComposer << "'" << endl; + s << "Arranger=\t" << "'" << m_trackArranger << "'" << endl; + s << "Message=\t" << "'" << m_trackMessage << "'" << endl; + + s << "Tracktitle=\t" << "'" << m_trackTitle << "'" << endl; + + s << "Tracknumber=\t" << m_trackNumber << endl; + + // track start + s << "Trackstart=\t" << m_trackStart.lba() << endl; + + // track length + s << "# Tracklength: " << m_trackLength.toString() << endl; + s << "Tracklength=\t" << m_trackLength.totalFrames() << ", 0" << endl; + + // pre-emphasis + s << "Pre-emphasis=\t"; + if( m_preEmphasis ) + s << "yes"; + else + s << "no"; + s << endl; + + // channels (always 2) + s << "Channels=\t2" << endl; + + // copy-permitted + // TODO: not sure about this! + // there are three options: yes, no, once + // but using "once" gives the same result as with cdrdao + // and that's important. + s << "Copy_permitted=\t"; + if( m_copyPermitted ) + s << "yes"; + else + s << "once"; + s << endl; + + // endianess - wav is little -> onthefly: big, with images: little + s << "Endianess=\t"; + if( m_bigEndian ) + s << "big"; + else + s << "little"; + s << endl; + + // write indices + // the current tracks' data contains the pregap of the next track + // if the pregap has length 0 we need no index 0 + if( m_indices.isEmpty() ) + s << "Index=\t\t0" << endl; + else { + for( unsigned int i = 0; i < m_indices.count(); ++i ) + s << "Index=\t\t" << m_indices[i] << endl; + } + + s << "Index0=\t\t" << m_index0 << endl; + + return ( s.device()->status() == IO_Ok ); +} + + +void K3bInfFileWriter::setTrack( const K3bDevice::Track& track ) +{ + m_indices.clear(); + + // the first index always has to be a zero (cdrecord manpage) + m_indices.append( 0 ); + + const QValueVector& indexList = track.indices(); + for( unsigned int i = 0; i < indexList.count(); ++i ) + m_indices.append( indexList[i].lba() ); + + if( track.index0() > 0 ) + m_index0 = track.index0().lba(); + else + m_index0 = -1; + + setPreEmphasis( track.preEmphasis() ); + setCopyPermitted( track.copyPermitted() ); + + setTrackStart( track.firstSector() ); + setTrackLength( track.length() ); + + setIsrc( track.isrc() ); + + setBigEndian( true ); +} + + +void K3bInfFileWriter::addIndex( long i ) +{ + m_indices.append( i ); +} + + +void K3bInfFileWriter::setTrackCdText( const K3bDevice::TrackCdText& cdtext ) +{ + setTrackTitle( cdtext.title() ); + setTrackPerformer( cdtext.performer() ); + setTrackSongwriter( cdtext.songwriter() ); + setTrackComposer( cdtext.composer() ); + setTrackArranger( cdtext.arranger() ); + setTrackMessage( cdtext.message() ); +} + + +void K3bInfFileWriter::setCdText( const K3bDevice::CdText& cdtext ) +{ + setAlbumTitle( cdtext.title() ); + setAlbumPerformer( cdtext.performer() ); +} diff --git a/libk3b/projects/k3binffilewriter.h b/libk3b/projects/k3binffilewriter.h new file mode 100644 index 0000000..74e23e4 --- /dev/null +++ b/libk3b/projects/k3binffilewriter.h @@ -0,0 +1,119 @@ +/* + * + * $Id: k3binffilewriter.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_INF_FILE_WRITER_H_ +#define _K3B_INF_FILE_WRITER_H_ + +#include +#include + +#include + + +namespace K3bDevice { + class Track; + class TrackCdText; + class CdText; +} + + +class K3bInfFileWriter +{ + public: + K3bInfFileWriter(); + + bool save( QTextStream& ); + bool save( const QString& filename ); + + /** + * Use this to set: + * @li trackStart + * @li trackLength + * @li index0 + * @li all indices + * @li preemphasis + * @li copyPermitted + * @li ISRC + * + * Endianess is set to big. + * + * Tracknumber needs to be set manually. + */ + void setTrack( const K3bDevice::Track& ); + + void clearIndices() { m_indices.clear(); } + + /** + * This is relative to the track start + */ + void setIndex0( int i ) { m_index0 = i; } + void addIndex( long i ); + + void setTrackNumber( int i ) { m_trackNumber = i; } + + void setTrackStart( const K3b::Msf& i ) { m_trackStart = i; } + void setTrackLength( const K3b::Msf& i ) { m_trackLength = i; } + + void setPreEmphasis( bool b ) { m_preEmphasis = b; } + void setCopyPermitted( bool b ) { m_copyPermitted = b; } + + /** + * Cdrecord seems to ignore this anyway and always expect big endian + * data on stdin and wavs are little endian anyway. + */ + void setBigEndian( bool b ) { m_bigEndian = b; } + + void setTrackCdText( const K3bDevice::TrackCdText& ); + void setTrackTitle( const QString& s ) { m_trackTitle = s; } + void setTrackPerformer( const QString& s ) { m_trackPerformer = s; } + void setTrackSongwriter( const QString& s ) { m_trackSongwriter = s; } + void setTrackComposer( const QString& s ) { m_trackComposer = s; } + void setTrackArranger( const QString& s ) { m_trackArranger = s; } + void setTrackMessage( const QString& s ) { m_trackMessage = s; } + + void setCdText( const K3bDevice::CdText& ); + void setAlbumTitle( const QString& s ) { m_albumTitle = s; } + void setAlbumPerformer( const QString& s ) { m_albumPerformer = s; } + + void setIsrc( const QCString& s ) { m_isrc = s; } + void setMcn( const QCString& s ) { m_mcn = s; } + + private: + long m_index0; + + QValueVector m_indices; + + int m_trackNumber; + K3b::Msf m_trackStart; + K3b::Msf m_trackLength; + bool m_preEmphasis; + bool m_copyPermitted; + bool m_bigEndian; + + QString m_trackTitle; + QString m_trackPerformer; + QString m_trackSongwriter; + QString m_trackComposer; + QString m_trackArranger; + QString m_trackMessage; + + QString m_albumTitle; + QString m_albumPerformer; + + QCString m_isrc; + QCString m_mcn; +}; + +#endif diff --git a/libk3b/projects/k3bpipebuffer.cpp b/libk3b/projects/k3bpipebuffer.cpp new file mode 100644 index 0000000..3b61116 --- /dev/null +++ b/libk3b/projects/k3bpipebuffer.cpp @@ -0,0 +1,281 @@ +/* + * + * $Id: k3bpipebuffer.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bpipebuffer.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +// +// This one is based on the little pipebuf2 program by Peter Osterlund +// + + +class K3bPipeBuffer::WorkThread : public K3bThread +{ +public: + WorkThread() + : K3bThread(), + buffer(0), + bufSize(4*1024*1024), + canceled(false) { + outFd = inFd = -1; + inFdPair[0] = inFdPair[1] = -1; + } + + ~WorkThread() { + delete [] buffer; + } + + bool initFds() { + if( inFd == -1 ) { + if( ::socketpair(AF_UNIX, SOCK_STREAM, 0, inFdPair) ) { + // if( ::pipe( inFdPair ) ) { + kdDebug() << "(K3bPipeBuffer::WorkThread) unable to create socketpair" << endl; + inFdPair[0] = inFdPair[1] = -1; + return false; + } + else { + ::fcntl(inFdPair[0], F_SETFL, O_NONBLOCK); + ::fcntl(outFd, F_SETFL, O_NONBLOCK); + } + } + else { + ::fcntl(inFd, F_SETFL, O_NONBLOCK); + } + + delete [] buffer; + buffer = new char[bufSize]; + + return (buffer != 0); + } + + void run() { + emitStarted(); + + int usedInFd = -1; + if( inFd > 0 ) + usedInFd = inFd; + else + usedInFd = inFdPair[0]; + + kdDebug() << "(K3bPipeBuffer::WorkThread) reading from " << usedInFd + << " and writing to " << outFd << endl; + kdDebug() << "(K3bPipeBuffer::WorkThread) using buffer size of " << bufSize << endl; + + // start the buffering + unsigned int bufPos = 0; + unsigned int dataLen = 0; + bool eof = false; + bool error = false; + canceled = false; + int oldPercent = 0; + + static const unsigned int MAX_BUFFER_READ = 2048*3; + + while( !canceled && !error && (!eof || dataLen > 0) ) { + // + // create two fd sets + // + fd_set readFds, writeFds; + FD_ZERO(&readFds); + FD_ZERO(&writeFds); + + // + // fill the fd sets + // + if( !eof && dataLen < bufSize ) + FD_SET(usedInFd, &readFds); + if( dataLen > 0 ) + FD_SET(outFd, &writeFds); + + // + // wait for data + // + int ret = select( QMAX(usedInFd, outFd) + 1, &readFds, &writeFds, NULL, NULL); + + // + // Do the buffering + // + if( !canceled && ret > 0 ) { + + int percent = -1; + + // + // Read from the buffer and write to the output + // + if( FD_ISSET(outFd, &writeFds) ) { + unsigned int maxLen = QMIN(bufSize - bufPos, dataLen); + + ret = ::write( outFd, &buffer[bufPos], maxLen ); + + if( ret < 0 ) { + if( (errno != EINTR) && (errno != EAGAIN) ) { + kdDebug() << "(K3bPipeBuffer::WorkThread) error while writing to " << outFd << endl; + error = true; + } + } + else { + // + // we always emit before the reading from the buffer since + // it makes way more sense to show the buffer before the reading. + // + percent = (int)((double)dataLen*100.0/(double)bufSize); + + bufPos = (bufPos + ret) % bufSize; + dataLen -= ret; + } + } + + // + // Read into the buffer + // + else if( FD_ISSET(usedInFd, &readFds) ) { + unsigned int readPos = (bufPos + dataLen) % bufSize; + unsigned int maxLen = QMIN(bufSize - readPos, bufSize - dataLen); + // + // never read more than xxx bytes + // This is some tuning to prevent the reading from blocking the whole thread + // + if( maxLen > MAX_BUFFER_READ ) // some dummy value below 1 MB + maxLen = MAX_BUFFER_READ; + ret = ::read( usedInFd, &buffer[readPos], maxLen ); + if( ret < 0 ) { + if( (errno != EINTR) && (errno != EAGAIN) ) { + kdDebug() << "(K3bPipeBuffer::WorkThread) error while reading from " << usedInFd << endl; + error = true; + } + } + else if( ret == 0 ) { + kdDebug() << "(K3bPipeBuffer::WorkThread) end of input." << endl; + eof = true; + } + else { + dataLen += ret; + + percent = (int)((double)dataLen*100.0/(double)bufSize); + } + } + + // A little hack to keep the buffer display from flickering + if( percent == 99 ) + percent = 100; + + if( percent != -1 && percent != oldPercent ) { + emitPercent( percent ); + oldPercent = percent; + } + } + else if( !canceled ) { + error = true; + kdDebug() << "(K3bPipeBuffer::WorkThread) select: " << ::strerror(errno) << endl; + } + } + + if( inFd == -1 ) { + ::close( inFdPair[0] ); + ::close( inFdPair[1] ); + inFdPair[0] = inFdPair[1] = -1; + } + + // + // close the fd we are writing to (this is need to make growisofs happy + // TODO: perhaps make this configurable + // + ::close( outFd ); + + if( canceled ) + emitCanceled(); + emitFinished( !error && !canceled ); + } + + char* buffer; + size_t bufSize; + int outFd; + int inFd; + int inFdPair[2]; + bool canceled; +}; + + +K3bPipeBuffer::K3bPipeBuffer( K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bThreadJob( jh, parent, name ) +{ + m_thread = new WorkThread(); + setThread( m_thread ); +} + + +K3bPipeBuffer::~K3bPipeBuffer() +{ + delete m_thread; +} + + +void K3bPipeBuffer::start() +{ + // + // Create the socketpair in the gui thread to be sure it's available after + // this method returns. + // + if( !m_thread->initFds() ) + jobFinished(false); + else + K3bThreadJob::start(); +} + + +void K3bPipeBuffer::cancel() +{ + m_thread->canceled = true; +} + + +void K3bPipeBuffer::setBufferSize( int mb ) +{ + m_thread->bufSize = mb * 1024 * 1024; +} + + +void K3bPipeBuffer::readFromFd( int fd ) +{ + m_thread->inFd = fd; +} + + +void K3bPipeBuffer::writeToFd( int fd ) +{ + m_thread->outFd = fd; +} + + +int K3bPipeBuffer::inFd() const +{ + if( m_thread->inFd == -1 ) + return m_thread->inFdPair[1]; + else + return m_thread->inFd; +} diff --git a/libk3b/projects/k3bpipebuffer.h b/libk3b/projects/k3bpipebuffer.h new file mode 100644 index 0000000..6aae368 --- /dev/null +++ b/libk3b/projects/k3bpipebuffer.h @@ -0,0 +1,59 @@ +/* + * + * $Id: k3bpipebuffer.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_PIPE_BUFFER_H_ +#define _K3B_PIPE_BUFFER_H_ + + +#include + +/** + * the pipebuffer uses the signal percent to show it's status. + */ +class K3bPipeBuffer : public K3bThreadJob +{ + public: + K3bPipeBuffer( K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bPipeBuffer(); + + /** + * Set the buffer size in MB. The default value is 4 MB. + */ + void setBufferSize( int ); + + /** + * If this is set to -1 (which is the default) the pipebuffer + * will create a fd pair which can be obtained by inFd() after + * the buffer has been started. + */ + void readFromFd( int fd ); + void writeToFd( int fd ); + + /** + * This is only valid after the piepbuffer has been started and no fd + * has been set with readFromFd. + */ + int inFd() const; + + public slots: + void start(); + void cancel(); + + private: + class WorkThread; + WorkThread* m_thread; +}; + +#endif diff --git a/libk3b/projects/k3btocfilewriter.cpp b/libk3b/projects/k3btocfilewriter.cpp new file mode 100644 index 0000000..77662d6 --- /dev/null +++ b/libk3b/projects/k3btocfilewriter.cpp @@ -0,0 +1,356 @@ +/* + * + * $Id: k3btocfilewriter.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3btocfilewriter.h" + +#include +#include +#include +#include + +#include +#include +#include + + +K3bTocFileWriter::K3bTocFileWriter() + : m_hideFirstTrack(false), + m_sessionToWrite(1) +{ +} + + +bool K3bTocFileWriter::save( const QString& filename ) +{ + QFile f( filename ); + + if( !f.open( IO_WriteOnly ) ) { + kdDebug() << "(K3bCueFileWriter) could not open file " << f.name() << endl; + return false; + } + + QTextStream s( &f ); + + return save( s ); +} + + +bool K3bTocFileWriter::save( QTextStream& t ) +{ + writeHeader(t); + + if( !m_cdText.isEmpty() ) + writeGlobalCdText(t); + + // + // see if we have multiple sessions + // + int sessions = 1; + for( K3bDevice::Toc::iterator it = m_toc.begin(); it != m_toc.end(); ++it ) { + if( (*it).session() > 1 ) + sessions = (*it).session(); + } + + if( m_sessionToWrite > sessions ) + m_sessionToWrite = 1; + + // + // We can only hide the first track if both the first and the second track are + // audio tracks. + // We also can only hide the first track in the first session. + // + bool hideFirstTrack = m_hideFirstTrack; + if( m_toc.count() < 2 || + m_toc[0].type() != K3bDevice::Track::AUDIO || + m_toc[1].type() != K3bDevice::Track::AUDIO || + (sessions > 1 && m_sessionToWrite != 1 ) ) + hideFirstTrack = false; + + + // the dataStart will be the offset in case we do not write the first session + K3b::Msf dataStart; + + unsigned int trackIndex = 0; + if( hideFirstTrack ) { + const K3bDevice::Track& hiddenTrack = m_toc[0]; + const K3bDevice::Track& track = m_toc[1]; + + t << "// Track number 1 (hidden) and track number 2 (as track 1)" << endl; + t << "TRACK AUDIO" << endl; + + if( track.copyPermitted() ) + t << "COPY" << endl; + else + t << "NO COPY" << endl; + + if( track.preEmphasis() ) + t << "PRE_EMPHASIS" << endl; + else + t << "NO PRE_EMPHASIS" << endl; + + if( !m_cdText.isEmpty() ) + writeTrackCdText( m_cdText[0], t ); + + // the "hidden" file will be used as pregap for the "first" track + t << "AUDIOFILE "; + writeDataSource( 0, t ); + if( readFromStdin() ) + t << hiddenTrack.firstSector().toString(); + else + t << " 0"; + t << " " << hiddenTrack.length().toString() << endl; + t << "START" << endl; // use the whole hidden file as pregap + + // now comes the "real" first track + t << "AUDIOFILE "; + writeDataSource( 1, t ); + if( readFromStdin() ) + t << track.firstSector().toString() << " "; + else + t << "0 "; + // no index 0 for the last track. Or should we allow this??? + if( m_toc.count() == 2 ) + t << track.length().toString(); + else + t << track.realAudioLength().toString(); + t << endl << endl; + + trackIndex+=2; + } + else { + // + // Seek to the first track to write. + // In case we hid the first track above it was the first track anyway. + // + while( m_toc[trackIndex].session() < m_sessionToWrite && + m_toc[trackIndex].session() > 0 ) + ++trackIndex; + + dataStart = m_toc[trackIndex].firstSector(); + } + + kdDebug() << "(K3bTocFileWriter) using offset of: " << dataStart.toString() << endl; + + while( trackIndex < m_toc.count() ) { + if( m_toc[trackIndex].session() == 0 || m_toc[trackIndex].session() == m_sessionToWrite ) + writeTrack( trackIndex, dataStart, t ); + trackIndex++; + } + + return ( t.device()->status() == IO_Ok ); +} + + +void K3bTocFileWriter::writeHeader( QTextStream& t ) +{ + // little comment + t << "// TOC-file to use with cdrdao created by K3b " << k3bcore->version() + << ", " << QDateTime::currentDateTime().toString() << endl << endl; + + t << "// " << m_toc.count() << " tracks" << endl; + if( m_toc.back().session() > 0 ) { + t << "// " << m_toc.back().session() << " sessions" << endl + << "// this is session number " << m_sessionToWrite << endl; + } + t << endl; + + // check the cd type + if( m_toc.contentType() == K3bDevice::AUDIO ) { + t << "CD_DA"; + } + else { + bool hasMode2Tracks = false; + for( K3bDevice::Toc::iterator it = m_toc.begin(); it != m_toc.end(); ++it ) { + const K3bDevice::Track& track = *it; + if( track.type() == K3bDevice::Track::DATA && + (track.mode() == K3bDevice::Track::MODE2 || + track.mode() == K3bDevice::Track::XA_FORM1 || + track.mode() == K3bDevice::Track::XA_FORM2 ) ) { + hasMode2Tracks = true; + break; + } + } + + if( hasMode2Tracks ) + t << "CD_ROM_XA"; + else + t << "CD_ROM"; + } + + t << endl << endl; +} + + +void K3bTocFileWriter::writeTrack( unsigned int index, const K3b::Msf& offset, QTextStream& t ) +{ + const K3bDevice::Track& track = m_toc[index]; + + t << "// Track number " << (index+1) << endl; + + if( track.type() == K3bDevice::Track::AUDIO ) { + t << "TRACK AUDIO" << endl; + + if( track.copyPermitted() ) + t << "COPY" << endl; + else + t << "NO COPY" << endl; + + if( track.preEmphasis() ) + t << "PRE_EMPHASIS" << endl; + else + t << "NO PRE_EMPHASIS" << endl; + + if( !m_cdText.isEmpty() ) + writeTrackCdText( m_cdText[index], t ); + + // + // cdrdao sees the pregap as part of the current track and not as part of + // the previous like it really is. + // + + if( index == 0 ) { + if( (track.firstSector()-offset) > 0 ) { + // + // the first track is the only track K3b does not generate null-pregap data for + // since cdrecord does not allow this. So We just do it here the same way and tell + // cdrdao to create the first pregap for us + // + + t << "PREGAP " + << (track.firstSector()-offset).toString() << endl; + } + } + else { + const K3bDevice::Track& lastTrack = m_toc[index-1]; + + // + // the pregap data + // + if( lastTrack.index0() > 0 ) { + t << "AUDIOFILE "; + writeDataSource( index-1, t ); + if( readFromStdin() ) + t << (lastTrack.firstSector() + lastTrack.index0() - offset).toString(); + else + t << (lastTrack.index0() - offset).toString(); + t << " " + << (lastTrack.length() - lastTrack.index0()).toString() + << endl + << "START" << endl; + } + } + + // + // The track data + // + t << "AUDIOFILE "; + writeDataSource( index, t ); + if( readFromStdin() ) + t << (track.firstSector() - offset).toString() << " "; + else + t << "0 "; + // no index 0 for the last track. Or should we allow this??? + if( index == m_toc.count()-1 ) + t << track.length().toString(); + else + t << track.realAudioLength().toString(); + t << endl; + } + else { + if( track.mode() == K3bDevice::Track::XA_FORM1 ) + t << "TRACK MODE2_FORM1" << endl; + else if( track.mode() == K3bDevice::Track::XA_FORM2 ) + t << "TRACK MODE2_FORM2" << endl; + else + t << "TRACK MODE1" << endl; + + if( !m_cdText.isEmpty() && !m_toc.contentType() != K3bDevice::DATA ) { + // + // insert fake cdtext + // cdrdao does not work without it and it seems not to do any harm. + // + t << "CD_TEXT {" << endl + << " LANGUAGE 0 {" << endl + << " TITLE " << "\"\"" << endl + << " PERFORMER " << "\"\"" << endl + << " ISRC " << "\"\"" << endl + << " ARRANGER " << "\"\"" << endl + << " SONGWRITER " << "\"\"" << endl + << " COMPOSER " << "\"\"" << endl + << " MESSAGE " << "\"\"" << endl + << " }" << endl + << "}" << endl; + } + + if( readFromStdin() ) + t << "DATAFILE \"-\" " << track.length().toString() << endl; + else + t << "DATAFILE \"" << m_filenames[index] << "\"" << endl; + t << endl; + } + + t << endl; +} + + +void K3bTocFileWriter::writeGlobalCdText( QTextStream& t ) +{ + t << "CD_TEXT {" << endl; + t << " LANGUAGE_MAP { 0: EN }" << endl; + t << " LANGUAGE 0 {" << endl; + t << " TITLE " << "\"" << m_cdText.title() << "\"" << endl; + t << " PERFORMER " << "\"" << m_cdText.performer() << "\"" << endl; + t << " DISC_ID " << "\"" << m_cdText.discId() << "\"" << endl; + t << " UPC_EAN " << "\"" << m_cdText.upcEan() << "\"" << endl; + t << endl; + t << " ARRANGER " << "\"" << m_cdText.arranger() << "\"" << endl; + t << " SONGWRITER " << "\"" << m_cdText.songwriter() << "\"" << endl; + t << " COMPOSER " << "\"" << m_cdText.composer() << "\"" << endl; + t << " MESSAGE " << "\"" << m_cdText.message() << "\"" << endl; + t << " }" << endl; + t << "}" << endl; + t << endl; +} + + +void K3bTocFileWriter::writeTrackCdText( const K3bDevice::TrackCdText& track, QTextStream& t ) +{ + t << "CD_TEXT {" << endl; + t << " LANGUAGE 0 {" << endl; + t << " TITLE " << "\"" << track.title() << "\"" << endl; + t << " PERFORMER " << "\"" << track.performer() << "\"" << endl; + t << " ISRC " << "\"" << track.isrc() << "\"" << endl; + t << " ARRANGER " << "\"" << track.arranger() << "\"" << endl; + t << " SONGWRITER " << "\"" << track.songwriter() << "\"" << endl; + t << " COMPOSER " << "\"" << track.composer() << "\"" << endl; + t << " MESSAGE " << "\"" << track.message() << "\"" << endl; + t << " }" << endl; + t << "}" << endl; +} + + +void K3bTocFileWriter::writeDataSource( unsigned int trackIndex, QTextStream& t ) +{ + if( readFromStdin() ) + t << "\"-\" "; + else + t << "\"" << m_filenames[trackIndex] << "\" "; +} + + +bool K3bTocFileWriter::readFromStdin() const +{ + return ( m_toc.count() > m_filenames.count() ); +} diff --git a/libk3b/projects/k3btocfilewriter.h b/libk3b/projects/k3btocfilewriter.h new file mode 100644 index 0000000..1c1da47 --- /dev/null +++ b/libk3b/projects/k3btocfilewriter.h @@ -0,0 +1,62 @@ +/* + * + * $Id: k3btocfilewriter.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_TOC_FILE_WRITER_H_ +#define _K3B_TOC_FILE_WRITER_H_ + +#include +#include + +#include +#include + +namespace K3bDevice { + class TrackCdText; +} + +class K3bTocFileWriter +{ + public: + K3bTocFileWriter(); + + bool save( QTextStream& ); + bool save( const QString& filename ); + + void setData( const K3bDevice::Toc& toc ) { m_toc = toc; } + void setCdText( const K3bDevice::CdText& text ) { m_cdText = text; } + void setFilenames( const QStringList& names ) { m_filenames = names; } + void setHideFirstTrack( bool b ) { m_hideFirstTrack = b; } + + /** + * The default is 1. + */ + void setSession( int s ) { m_sessionToWrite = s; } + + private: + void writeHeader( QTextStream& t ); + void writeGlobalCdText( QTextStream& t ); + void writeTrackCdText( const K3bDevice::TrackCdText& track, QTextStream& t ); + void writeTrack( unsigned int index, const K3b::Msf& offset, QTextStream& t ); + void writeDataSource( unsigned int trackNumber, QTextStream& t ); + bool readFromStdin() const; + + K3bDevice::Toc m_toc; + K3bDevice::CdText m_cdText; + QStringList m_filenames; + bool m_hideFirstTrack; + int m_sessionToWrite; +}; + +#endif diff --git a/libk3b/projects/mixedcd/Makefile.am b/libk3b/projects/mixedcd/Makefile.am new file mode 100644 index 0000000..fb5f44c --- /dev/null +++ b/libk3b/projects/mixedcd/Makefile.am @@ -0,0 +1,23 @@ +# we need the ../datacd and ../audiocd for the uic generated header files +AM_CPPFLAGS= -I$(srcdir)/../../core \ + -I$(srcdir)/../../plugin \ + -I$(srcdir)/../../../libk3bdevice \ + -I$(srcdir)/../../../src \ + -I$(srcdir)/../../tools \ + -I$(srcdir)/.. \ + -I$(srcdir)/../datacd \ + -I$(srcdir)/../audiocd \ + -I$(srcdir)/../../plugin \ + -I../datacd \ + -I../audiocd \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libmixed.la + +libmixed_la_SOURCES = k3bmixeddoc.cpp \ + k3bmixedjob.cpp + +include_HEADERS = k3bmixeddoc.h \ + k3bmixedjob.h diff --git a/libk3b/projects/mixedcd/k3bmixeddoc.cpp b/libk3b/projects/mixedcd/k3bmixeddoc.cpp new file mode 100644 index 0000000..a2c76b0 --- /dev/null +++ b/libk3b/projects/mixedcd/k3bmixeddoc.cpp @@ -0,0 +1,249 @@ +/* + * + * $Id: k3bmixeddoc.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bmixeddoc.h" +#include "k3bmixedjob.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + + +K3bMixedDoc::K3bMixedDoc( QObject* parent ) + : K3bDoc( parent ) +{ + m_dataDoc = new K3bDataDoc( this ); + m_audioDoc = new K3bAudioDoc( this ); + + connect( m_dataDoc, SIGNAL(changed()), + this, SIGNAL(changed()) ); + connect( m_audioDoc, SIGNAL(changed()), + this, SIGNAL(changed()) ); +} + + +K3bMixedDoc::~K3bMixedDoc() +{ +} + + +bool K3bMixedDoc::newDocument() +{ + m_dataDoc->newDocument(); + m_audioDoc->newDocument(); + + return K3bDoc::newDocument(); +} + + +QString K3bMixedDoc::name() const +{ + return m_dataDoc->name(); +} + + +void K3bMixedDoc::setURL( const KURL& url ) +{ + K3bDoc::setURL( url ); + m_audioDoc->setURL( url ); + m_dataDoc->setURL( url ); +} + + +void K3bMixedDoc::setModified( bool m ) +{ + m_audioDoc->setModified( m ); + m_dataDoc->setModified( m ); +} + + +bool K3bMixedDoc::isModified() const +{ + return ( m_audioDoc->isModified() || m_dataDoc->isModified() ); +} + + +KIO::filesize_t K3bMixedDoc::size() const +{ + return m_dataDoc->size() + m_audioDoc->size(); +} + +K3b::Msf K3bMixedDoc::length() const +{ + return m_dataDoc->length() + m_audioDoc->length(); +} + + +int K3bMixedDoc::numOfTracks() const +{ + return m_audioDoc->numOfTracks() + 1; +} + + +K3bBurnJob* K3bMixedDoc::newBurnJob( K3bJobHandler* hdl, QObject* parent ) +{ + return new K3bMixedJob( this, hdl, parent ); +} + + +void K3bMixedDoc::addUrls( const KURL::List& urls ) +{ + dataDoc()->addUrls( urls ); +} + + +bool K3bMixedDoc::loadDocumentData( QDomElement* rootElem ) +{ + QDomNodeList nodes = rootElem->childNodes(); + + if( nodes.length() < 4 ) + return false; + + if( nodes.item(0).nodeName() != "general" ) + return false; + if( !readGeneralDocumentData( nodes.item(0).toElement() ) ) + return false; + + if( nodes.item(1).nodeName() != "audio" ) + return false; + QDomElement audioElem = nodes.item(1).toElement(); + if( !m_audioDoc->loadDocumentData( &audioElem ) ) + return false; + + if( nodes.item(2).nodeName() != "data" ) + return false; + QDomElement dataElem = nodes.item(2).toElement(); + if( !m_dataDoc->loadDocumentData( &dataElem ) ) + return false; + + if( nodes.item(3).nodeName() != "mixed" ) + return false; + + QDomNodeList optionList = nodes.item(3).childNodes(); + for( uint i = 0; i < optionList.count(); i++ ) { + + QDomElement e = optionList.item(i).toElement(); + if( e.isNull() ) + return false; + + if( e.nodeName() == "remove_buffer_files" ) + setRemoveImages( e.toElement().text() == "yes" ); + else if( e.nodeName() == "image_path" ) + setTempDir( e.toElement().text() ); + else if( e.nodeName() == "mixed_type" ) { + QString mt = e.toElement().text(); + if( mt == "last_track" ) + setMixedType( DATA_LAST_TRACK ); + else if( mt == "second_session" ) + setMixedType( DATA_SECOND_SESSION ); + else + setMixedType( DATA_FIRST_TRACK ); + } + } + + return true; +} + + +bool K3bMixedDoc::saveDocumentData( QDomElement* docElem ) +{ + QDomDocument doc = docElem->ownerDocument(); + saveGeneralDocumentData( docElem ); + + QDomElement audioElem = doc.createElement( "audio" ); + m_audioDoc->saveDocumentData( &audioElem ); + docElem->appendChild( audioElem ); + + QDomElement dataElem = doc.createElement( "data" ); + m_dataDoc->saveDocumentData( &dataElem ); + docElem->appendChild( dataElem ); + + QDomElement mixedElem = doc.createElement( "mixed" ); + docElem->appendChild( mixedElem ); + + QDomElement bufferFilesElem = doc.createElement( "remove_buffer_files" ); + bufferFilesElem.appendChild( doc.createTextNode( removeImages() ? "yes" : "no" ) ); + mixedElem.appendChild( bufferFilesElem ); + + QDomElement imagePathElem = doc.createElement( "image_path" ); + imagePathElem.appendChild( doc.createTextNode( tempDir() ) ); + mixedElem.appendChild( imagePathElem ); + + QDomElement mixedTypeElem = doc.createElement( "mixed_type" ); + switch( mixedType() ) { + case DATA_FIRST_TRACK: + mixedTypeElem.appendChild( doc.createTextNode( "first_track" ) ); + break; + case DATA_LAST_TRACK: + mixedTypeElem.appendChild( doc.createTextNode( "last_track" ) ); + break; + case DATA_SECOND_SESSION: + mixedTypeElem.appendChild( doc.createTextNode( "second_session" ) ); + break; + } + mixedElem.appendChild( mixedTypeElem ); + + setModified( false ); + + return true; +} + + +K3bDevice::Toc K3bMixedDoc::toToc( int dataMode, const K3b::Msf& dataTrackLength ) const +{ + // !inaccurate datatrack size! + K3bDevice::Track dataTrack( 0, dataTrackLength > 0 ? dataTrackLength-1 : m_dataDoc->length()-1, + K3bDevice::Track::DATA, dataMode ); + K3bDevice::Toc toc = audioDoc()->toToc(); + if( mixedType() == DATA_FIRST_TRACK ) { + // fix the audio tracks' sectors + for( K3bDevice::Toc::iterator it = toc.begin(); it != toc.end(); ++it ) { + (*it).setLastSector( (*it).lastSector() + dataTrack.length() ); + (*it).setFirstSector( (*it).firstSector() + dataTrack.length() ); + } + toc.insert( toc.begin(), dataTrack ); + } + else { + // fix the datatrack's sectors + dataTrack.setLastSector( dataTrack.lastSector() + toc.back().lastSector()+1 ); + dataTrack.setFirstSector( toc.back().lastSector()+1 ); + toc.append( dataTrack ); + + if( mixedType() == DATA_SECOND_SESSION ) { + // fix the session numbers + for( K3bDevice::Toc::iterator it = toc.begin(); it != toc.end(); ++it ) { + if( (*it).type() == K3bDevice::Track::DATA ) + (*it).setSession( 2 ); + else + (*it).setSession( 1 ); + } + } + } + + return toc; +} + +#include "k3bmixeddoc.moc" + diff --git a/libk3b/projects/mixedcd/k3bmixeddoc.h b/libk3b/projects/mixedcd/k3bmixeddoc.h new file mode 100644 index 0000000..7d71b39 --- /dev/null +++ b/libk3b/projects/mixedcd/k3bmixeddoc.h @@ -0,0 +1,95 @@ +/* + * + * $Id: k3bmixeddoc.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_MIXED_DOC_H +#define K3B_MIXED_DOC_H + +#include +#include +#include + +#include +#include "k3b_export.h" +class QDomDocument; +class QDomElement; +class K3bBurnJob; +//class K3bView; +class QWidget; +class KConfig; + + +class LIBK3B_EXPORT K3bMixedDoc : public K3bDoc +{ + Q_OBJECT + + public: + K3bMixedDoc( QObject* parent = 0 ); + ~K3bMixedDoc(); + + QString name() const; + + bool newDocument(); + + void setModified( bool m = true ); + bool isModified() const; + + KIO::filesize_t size() const; + K3b::Msf length() const; + + int numOfTracks() const; + + K3bBurnJob* newBurnJob( K3bJobHandler*, QObject* parent = 0 ); + + K3bAudioDoc* audioDoc() const { return m_audioDoc; } + K3bDataDoc* dataDoc() const { return m_dataDoc; } + + enum MixedType { DATA_FIRST_TRACK, + DATA_LAST_TRACK, + DATA_SECOND_SESSION }; + + int mixedType() const { return m_mixedType; } + int type() const { return MIXED; } + + void setURL( const KURL& url ); + + /** + * Represent the structure of the doc as CD Table of Contents. + * Be aware that the length of the data track is just an estimate + * and needs to be corrected if not specified here. + * + * @param dataMode mode of the data track (MODE1 or XA_FORM1) + * @param dataTrackLength exact length of the dataTrack + */ + + K3bDevice::Toc toToc( int dataMode, const K3b::Msf& dataTrackLength = 0 ) const; + + public slots: + void setMixedType( MixedType t ) { m_mixedType = t; } + void addUrls( const KURL::List& urls ); + + protected: + bool loadDocumentData( QDomElement* ); + bool saveDocumentData( QDomElement* ); + QString typeString() const { return "mixed"; } + + private: + K3bDataDoc* m_dataDoc; + K3bAudioDoc* m_audioDoc; + + int m_mixedType; +}; + + +#endif diff --git a/libk3b/projects/mixedcd/k3bmixedjob.cpp b/libk3b/projects/mixedcd/k3bmixedjob.cpp new file mode 100644 index 0000000..a4be92c --- /dev/null +++ b/libk3b/projects/mixedcd/k3bmixedjob.cpp @@ -0,0 +1,1339 @@ +/* + * + * $Id: k3bmixedjob.cpp 690212 2007-07-20 11:02:13Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + + +#include "k3bmixedjob.h" +#include "k3bmixeddoc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +static QString createNonExistingFilesString( const QValueList& items, unsigned int max ) +{ + QString s; + unsigned int cnt = 0; + for( QValueList::const_iterator it = items.begin(); + it != items.end(); ++it ) { + + s += KStringHandler::csqueeze( (*it)->filename(), 60 ); + + ++cnt; + if( cnt >= max || it == items.end() ) + break; + + s += "
"; + } + + if( items.count() > max ) + s += "..."; + + return s; +} + + + +class K3bMixedJob::Private +{ +public: + Private() + : maxSpeedJob(0) { + } + + + int copies; + int copiesDone; + + K3bAudioMaxSpeedJob* maxSpeedJob; + bool maxSpeed; +}; + + +K3bMixedJob::K3bMixedJob( K3bMixedDoc* doc, K3bJobHandler* hdl, QObject* parent ) + : K3bBurnJob( hdl, parent ), + m_doc( doc ), + m_normalizeJob(0) +{ + d = new Private; + + m_isoImager = new K3bIsoImager( doc->dataDoc(), this, this ); + connect( m_isoImager, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_isoImager, SIGNAL(percent(int)), this, SLOT(slotIsoImagerPercent(int)) ); + connect( m_isoImager, SIGNAL(finished(bool)), this, SLOT(slotIsoImagerFinished(bool)) ); + connect( m_isoImager, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + + m_audioImager = new K3bAudioImager( doc->audioDoc(), this, this ); + connect( m_audioImager, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_audioImager, SIGNAL(percent(int)), this, SLOT(slotAudioDecoderPercent(int)) ); + connect( m_audioImager, SIGNAL(subPercent(int)), this, SLOT(slotAudioDecoderSubPercent(int)) ); + connect( m_audioImager, SIGNAL(finished(bool)), this, SLOT(slotAudioDecoderFinished(bool)) ); + connect( m_audioImager, SIGNAL(nextTrack(int, int)), this, SLOT(slotAudioDecoderNextTrack(int, int)) ); + + m_msInfoFetcher = new K3bMsInfoFetcher( this, this ); + connect( m_msInfoFetcher, SIGNAL(finished(bool)), this, SLOT(slotMsInfoFetched(bool)) ); + connect( m_msInfoFetcher, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + + m_writer = 0; + m_tocFile = 0; + m_tempData = new K3bAudioJobTempData( m_doc->audioDoc(), this ); +} + + +K3bMixedJob::~K3bMixedJob() +{ + delete m_tocFile; + delete d; +} + + +K3bDevice::Device* K3bMixedJob::writer() const +{ + if( m_doc->onlyCreateImages() ) + return 0; + else + return m_doc->burner(); +} + + +K3bDoc* K3bMixedJob::doc() const +{ + return m_doc; +} + + +void K3bMixedJob::start() +{ + jobStarted(); + + m_canceled = false; + m_errorOccuredAndAlreadyReported = false; + d->copiesDone = 0; + d->copies = m_doc->copies(); + m_currentAction = PREPARING_DATA; + d->maxSpeed = false; + + if( m_doc->dummy() ) + d->copies = 1; + + prepareProgressInformation(); + + // + // Check if all files exist + // + QValueList nonExistingFiles; + K3bAudioTrack* track = m_doc->audioDoc()->firstTrack(); + while( track ) { + K3bAudioDataSource* source = track->firstSource(); + while( source ) { + if( K3bAudioFile* file = dynamic_cast( source ) ) { + if( !QFile::exists( file->filename() ) ) + nonExistingFiles.append( file ); + } + source = source->next(); + } + track = track->next(); + } + if( !nonExistingFiles.isEmpty() ) { + if( questionYesNo( "

" + i18n("The following files could not be found. Do you want to remove them from the " + "project and continue without adding them to the image?") + + "

" + createNonExistingFilesString( nonExistingFiles, 10 ), + i18n("Warning"), + i18n("Remove missing files and continue"), + i18n("Cancel and go back") ) ) { + for( QValueList::const_iterator it = nonExistingFiles.begin(); + it != nonExistingFiles.end(); ++it ) { + delete *it; + } + } + else { + m_canceled = true; + emit canceled(); + jobFinished(false); + return; + } + } + + // + // Make sure the project is not empty + // + if( m_doc->audioDoc()->numOfTracks() == 0 ) { + emit infoMessage( i18n("Please add files to your project first."), ERROR ); + jobFinished(false); + return; + } + + + // set some flags that are needed + m_doc->audioDoc()->setOnTheFly( m_doc->onTheFly() ); // for the toc writer + m_doc->audioDoc()->setHideFirstTrack( false ); // unsupported + m_doc->dataDoc()->setBurner( m_doc->burner() ); // so the isoImager can read ms data + + emit newTask( i18n("Preparing data") ); + + determineWritingMode(); + + // + // First we make sure the data portion is valid + // + + // we do not have msinfo yet + m_currentAction = INITIALIZING_IMAGER; + m_isoImager->setMultiSessionInfo( QString::null ); + m_isoImager->init(); +} + + +void K3bMixedJob::startFirstCopy() +{ + // + // if not onthefly create the iso image and then the wavs + // and write then + // if onthefly calculate the iso size + // + if( m_doc->onTheFly() ) { + if( m_doc->speed() == 0 ) { + emit newSubTask( i18n("Determining maximum writing speed") ); + + // + // try to determine the max possible speed + // no need to check the data track's max speed. Most current systems are able + // to handle the maxium possible + // + if( !d->maxSpeedJob ) { + // the maxspeed job gets the device from the doc: + m_doc->audioDoc()->setBurner( m_doc->burner() ); + d->maxSpeedJob = new K3bAudioMaxSpeedJob( m_doc->audioDoc(), this, this ); + connect( d->maxSpeedJob, SIGNAL(percent(int)), + this, SIGNAL(subPercent(int)) ); + connect( d->maxSpeedJob, SIGNAL(finished(bool)), + this, SLOT(slotMaxSpeedJobFinished(bool)) ); + } + d->maxSpeedJob->start(); + } + else if( m_doc->mixedType() != K3bMixedDoc::DATA_SECOND_SESSION ) { + m_currentAction = PREPARING_DATA; + m_isoImager->calculateSize(); + } + else { + // we cannot calculate the size since we don't have the msinfo yet + // so first write the audio session + writeNextCopy(); + } + } + else { + emit burning(false); + + emit infoMessage( i18n("Creating audio image files in %1").arg(m_doc->tempDir()), INFO ); + + m_tempFilePrefix = K3b::findUniqueFilePrefix( ( !m_doc->audioDoc()->title().isEmpty() + ? m_doc->audioDoc()->title() + : m_doc->dataDoc()->isoOptions().volumeID() ), + m_doc->tempDir() ); + + m_tempData->prepareTempFileNames( m_doc->tempDir() ); + QStringList filenames; + for( K3bAudioTrack* track = m_doc->audioDoc()->firstTrack(); track; track = track->next() ) + filenames += m_tempData->bufferFileName( track ); + m_audioImager->setImageFilenames( filenames ); + + if( m_doc->mixedType() != K3bMixedDoc::DATA_SECOND_SESSION ) { + createIsoImage(); + } + else { + emit newTask( i18n("Creating audio image files") ); + m_currentAction = CREATING_AUDIO_IMAGE; + m_audioImager->start(); + } + } +} + + +void K3bMixedJob::slotMaxSpeedJobFinished( bool success ) +{ + d->maxSpeed = success; + if( !success ) + emit infoMessage( i18n("Unable to determine maximum speed for some reason. Ignoring."), WARNING ); + + if( m_doc->mixedType() != K3bMixedDoc::DATA_SECOND_SESSION ) { + m_currentAction = PREPARING_DATA; + m_isoImager->calculateSize(); + } + else { + // we cannot calculate the size since we don't have the msinfo yet + // so first write the audio session + writeNextCopy(); + } +} + + +void K3bMixedJob::writeNextCopy() +{ + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + m_currentAction = WRITING_AUDIO_IMAGE; + if( !prepareWriter() || !startWriting() ) { + cleanupAfterError(); + jobFinished(false); + } + else if( m_doc->onTheFly() ) + m_audioImager->start(); + } + else { + // the prepareWriter method needs the action to be set + if( m_doc->mixedType() == K3bMixedDoc::DATA_LAST_TRACK ) + m_currentAction = WRITING_AUDIO_IMAGE; + else + m_currentAction = WRITING_ISO_IMAGE; + + if( !prepareWriter() || !startWriting() ) { + cleanupAfterError(); + jobFinished(false); + } + else if( m_doc->onTheFly() ) { + if( m_doc->mixedType() == K3bMixedDoc::DATA_LAST_TRACK ) + m_audioImager->start(); + else + m_isoImager->start(); + } + } +} + + +void K3bMixedJob::cancel() +{ + m_canceled = true; + + if( d->maxSpeedJob ) + d->maxSpeedJob->cancel(); + + if( m_writer ) + m_writer->cancel(); + m_isoImager->cancel(); + m_audioImager->cancel(); + m_msInfoFetcher->cancel(); + emit infoMessage( i18n("Writing canceled."), K3bJob::ERROR ); + removeBufferFiles(); + emit canceled(); + jobFinished(false); +} + + +void K3bMixedJob::slotMsInfoFetched( bool success ) +{ + if( m_canceled || m_errorOccuredAndAlreadyReported ) + return; + + if( success ) { + if( m_usedDataWritingApp == K3b::CDRECORD ) + m_isoImager->setMultiSessionInfo( m_msInfoFetcher->msInfo() ); + else // cdrdao seems to write a 150 blocks pregap that is not used by cdrecord + m_isoImager->setMultiSessionInfo( QString("%1,%2") + .arg(m_msInfoFetcher->lastSessionStart()) + .arg(m_msInfoFetcher->nextSessionStart()+150) ); + + if( m_doc->onTheFly() ) { + m_currentAction = PREPARING_DATA; + m_isoImager->calculateSize(); + } + else { + createIsoImage(); + } + } + else { + // the MsInfoFetcher already emitted failure info + cleanupAfterError(); + jobFinished(false); + } +} + + +void K3bMixedJob::slotIsoImagerFinished( bool success ) +{ + if( m_canceled || m_errorOccuredAndAlreadyReported ) + return; + + // + // Initializing imager before the first copy + // + if( m_currentAction == INITIALIZING_IMAGER ) { + if( success ) { + m_currentAction = PREPARING_DATA; + + // check the size + m_projectSize = m_isoImager->size() + m_doc->audioDoc()->length(); + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) + m_projectSize += 11400; // the session gap + + startFirstCopy(); + } + else { + cleanupAfterError(); + jobFinished( false ); + } + } + + // + // Recalculated iso image size + // + else if( m_currentAction == PREPARING_DATA ) { + if( success ) { + // 1. data in first track: + // start isoimager and writer + // when isoimager finishes start audiodecoder + + // 2. data in last track + // start audiodecoder and writer + // when audiodecoder finishes start isoimager + + // 3. data in second session + // start audiodecoder and writer + // start isoimager and writer + + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + m_currentAction = WRITING_ISO_IMAGE; + if( !prepareWriter() || !startWriting() ) { + cleanupAfterError(); + jobFinished(false); + } + else + m_isoImager->start(); + } + else + writeNextCopy(); + } + else { + cleanupAfterError(); + jobFinished( false ); + } + } + + // + // Image creation finished + // + else { + if( !success ) { + emit infoMessage( i18n("Error while creating ISO image."), ERROR ); + cleanupAfterError(); + + jobFinished( false ); + return; + } + + if( m_doc->onTheFly() ) { + if( m_doc->mixedType() == K3bMixedDoc::DATA_FIRST_TRACK ) { + m_currentAction = WRITING_AUDIO_IMAGE; + m_audioImager->start(); + } + } + else { + emit infoMessage( i18n("ISO image successfully created."), SUCCESS ); + + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + m_currentAction = WRITING_ISO_IMAGE; + + if( !prepareWriter() || !startWriting() ) { + cleanupAfterError(); + jobFinished(false); + } + } + else { + emit newTask( i18n("Creating audio image files") ); + m_currentAction = CREATING_AUDIO_IMAGE; + m_audioImager->start(); + } + } + } +} + + +void K3bMixedJob::slotWriterFinished( bool success ) +{ + if( m_canceled || m_errorOccuredAndAlreadyReported ) + return; + + if( !success ) { + cleanupAfterError(); + jobFinished(false); + return; + } + + emit burning(false); + + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION && m_currentAction == WRITING_AUDIO_IMAGE ) { + // reload the media (as a subtask so the user does not see the "Flushing cache" or "Fixating" messages while + // doing so + emit newSubTask( i18n("Reloading the medium") ); + connect( K3bDevice::reload( m_doc->burner() ), SIGNAL(finished(bool)), + this, SLOT(slotMediaReloadedForSecondSession(bool)) ); + } + else { + d->copiesDone++; + if( d->copiesDone < d->copies ) { + K3bDevice::eject( m_doc->burner() ); + writeNextCopy(); + } + else { + if( !m_doc->onTheFly() && m_doc->removeImages() ) + removeBufferFiles(); + + if( k3bcore->globalSettings()->ejectMedia() ) + K3bDevice::eject( m_doc->burner() ); + + jobFinished(true); + } + } +} + + +void K3bMixedJob::slotMediaReloadedForSecondSession( bool success ) +{ + if( !success ) + blockingInformation( i18n("Please reload the medium and press 'ok'"), + i18n("Unable to close the tray") ); + + // start the next session + m_currentAction = WRITING_ISO_IMAGE; + if( d->copiesDone > 0 ) { + // we only create the image once. This should not be a problem??? + if( !prepareWriter() || !startWriting() ) { + cleanupAfterError(); + jobFinished(false); + } + else if( m_doc->onTheFly() ) { + m_isoImager->start(); + } + } + else if( m_doc->dummy() ) { + // do not try to get ms info in simulation mode since the cd is empty! + if( m_doc->onTheFly() ) { + m_currentAction = PREPARING_DATA; + m_isoImager->calculateSize(); + } + else + createIsoImage(); + } + else { + m_currentAction = FETCHING_MSINFO; + m_msInfoFetcher->setDevice( m_doc->burner() ); + m_msInfoFetcher->start(); + } +} + + +void K3bMixedJob::slotAudioDecoderFinished( bool success ) +{ + if( m_canceled || m_errorOccuredAndAlreadyReported ) + return; + + if( !success ) { + emit infoMessage( i18n("Error while decoding audio tracks."), ERROR ); + cleanupAfterError(); + jobFinished(false); + return; + } + + if( m_doc->onTheFly() ) { + if( m_doc->mixedType() == K3bMixedDoc::DATA_LAST_TRACK ) { + m_currentAction = WRITING_ISO_IMAGE; + m_isoImager->start(); + } + } + else { + emit infoMessage( i18n("Audio images successfully created."), SUCCESS ); + + if( m_doc->audioDoc()->normalize() ) { + normalizeFiles(); + } + else { + if( m_doc->mixedType() == K3bMixedDoc::DATA_FIRST_TRACK ) + m_currentAction = WRITING_ISO_IMAGE; + else + m_currentAction = WRITING_AUDIO_IMAGE; + + if( !prepareWriter() || !startWriting() ) { + cleanupAfterError(); + jobFinished(false); + } + } + } +} + + +void K3bMixedJob::slotAudioDecoderNextTrack( int t, int tt ) +{ + if( m_doc->onlyCreateImages() || !m_doc->onTheFly() ) { + K3bAudioTrack* track = m_doc->audioDoc()->getTrack(t); + emit newSubTask( i18n("Decoding audio track %1 of %2%3") + .arg(t) + .arg(tt) + .arg( track->title().isEmpty() || track->artist().isEmpty() + ? QString::null + : " (" + track->artist() + " - " + track->title() + ")" ) ); + } +} + + +bool K3bMixedJob::prepareWriter() +{ + if( m_writer ) delete m_writer; + + if( ( m_currentAction == WRITING_ISO_IMAGE && m_usedDataWritingApp == K3b::CDRECORD ) || + ( m_currentAction == WRITING_AUDIO_IMAGE && m_usedAudioWritingApp == K3b::CDRECORD ) ) { + + if( !writeInfFiles() ) { + kdDebug() << "(K3bMixedJob) could not write inf-files." << endl; + emit infoMessage( i18n("IO Error"), ERROR ); + + return false; + } + + K3bCdrecordWriter* writer = new K3bCdrecordWriter( m_doc->burner(), this, this ); + + // only write the audio tracks in DAO mode + if( m_currentAction == WRITING_ISO_IMAGE ) + writer->setWritingMode( m_usedDataWritingMode ); + else + writer->setWritingMode( m_usedAudioWritingMode ); + + writer->setSimulate( m_doc->dummy() ); + writer->setBurnSpeed( m_doc->speed() ); + + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + if( m_currentAction == WRITING_ISO_IMAGE ) { + if( m_doc->onTheFly() ) + writer->addArgument("-waiti"); + + addDataTrack( writer ); + } + else { + writer->addArgument("-multi"); + addAudioTracks( writer ); + } + } + else { + if( m_doc->mixedType() == K3bMixedDoc::DATA_FIRST_TRACK ) + addDataTrack( writer ); + addAudioTracks( writer ); + if( m_doc->mixedType() == K3bMixedDoc::DATA_LAST_TRACK ) + addDataTrack( writer ); + } + + m_writer = writer; + } + else { + if( !writeTocFile() ) { + kdDebug() << "(K3bDataJob) could not write tocfile." << endl; + emit infoMessage( i18n("IO Error"), ERROR ); + + return false; + } + + // create the writer + // create cdrdao job + K3bCdrdaoWriter* writer = new K3bCdrdaoWriter( m_doc->burner(), this, this ); + writer->setSimulate( m_doc->dummy() ); + writer->setBurnSpeed( m_doc->speed() ); + + // multisession only for the first session + writer->setMulti( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION + && m_currentAction == WRITING_AUDIO_IMAGE ); + + writer->setTocFile( m_tocFile->name() ); + + m_writer = writer; + } + + connect( m_writer, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_writer, SIGNAL(percent(int)), this, SLOT(slotWriterJobPercent(int)) ); + connect( m_writer, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSize(int, int)) ); + connect( m_writer, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); + connect( m_writer, SIGNAL(processedSubSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( m_writer, SIGNAL(nextTrack(int, int)), this, SLOT(slotWriterNextTrack(int, int)) ); + connect( m_writer, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) ); + connect( m_writer, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); + connect( m_writer, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + connect( m_writer, SIGNAL(finished(bool)), this, SLOT(slotWriterFinished(bool)) ); + // connect( m_writer, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) ); + connect( m_writer, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_writer, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + + return true; +} + + +bool K3bMixedJob::writeInfFiles() +{ + K3bInfFileWriter infFileWriter; + K3bAudioTrack* track = m_doc->audioDoc()->firstTrack(); + while( track ) { + + infFileWriter.setTrack( track->toCdTrack() ); + infFileWriter.setTrackNumber( track->trackNumber() ); + if( !m_doc->onTheFly() ) + infFileWriter.setBigEndian( false ); + + if( !infFileWriter.save( m_tempData->infFileName(track) ) ) + return false; + + track = track->next(); + } + return true; +} + + +bool K3bMixedJob::writeTocFile() +{ + // FIXME: create the tocfile in the same directory like all the other files. + + if( m_tocFile ) delete m_tocFile; + m_tocFile = new KTempFile( QString::null, "toc" ); + m_tocFile->setAutoDelete(true); + + // write the toc-file + if( QTextStream* s = m_tocFile->textStream() ) { + + K3bTocFileWriter tocFileWriter; + + // + // TOC + // + tocFileWriter.setData( m_doc->toToc( m_usedDataMode == K3b::MODE2 + ? K3bDevice::Track::XA_FORM1 + : K3bDevice::Track::MODE1, + m_doc->onTheFly() + ? m_isoImager->size() + : m_doc->dataDoc()->length() ) ); + + // + // CD-Text + // + if( m_doc->audioDoc()->cdText() ) { + K3bDevice::CdText text = m_doc->audioDoc()->cdTextData(); + // if data in first track we need to add a dummy cdtext + if( m_doc->mixedType() == K3bMixedDoc::DATA_FIRST_TRACK ) + text.insert( text.begin(), K3bDevice::TrackCdText() ); + + tocFileWriter.setCdText( text ); + } + + // + // Session to write + // + tocFileWriter.setSession( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION && + m_currentAction == WRITING_ISO_IMAGE ? 2 : 1 ); + + // + // image filenames + // + if( !m_doc->onTheFly() ) { + QStringList files; + K3bAudioTrack* track = m_doc->audioDoc()->firstTrack(); + while( track ) { + files += m_tempData->bufferFileName( track ); + track = track->next(); + } + if( m_doc->mixedType() == K3bMixedDoc::DATA_FIRST_TRACK ) + files.prepend( m_isoImageFilePath ); + else + files.append( m_isoImageFilePath ); + + tocFileWriter.setFilenames( files ); + } + + bool success = tocFileWriter.save( *s ); + + m_tocFile->close(); + + // backup for debugging +// KIO::NetAccess::del("/tmp/trueg/tocfile_debug_backup.toc",0L); +// KIO::NetAccess::copy( m_tocFile->name(), "/tmp/trueg/tocfile_debug_backup.toc",0L ); + + return success; + } + else + return false; +} + + +void K3bMixedJob::addAudioTracks( K3bCdrecordWriter* writer ) +{ + writer->addArgument( "-useinfo" ); + + // add raw cdtext data + if( m_doc->audioDoc()->cdText() ) { + writer->setRawCdText( m_doc->audioDoc()->cdTextData().rawPackData() ); + } + + writer->addArgument( "-audio" ); + + // we always pad because although K3b makes sure all tracks' length are multiples of 2352 + // it seems that normalize sometimes corrupts these lengths + // FIXME: see K3bAudioJob for the whole less4secs and zeroPregap handling + writer->addArgument( "-pad" ); + + // Allow tracks shorter than 4 seconds + writer->addArgument( "-shorttrack" ); + + // add all the audio tracks + K3bAudioTrack* track = m_doc->audioDoc()->firstTrack(); + while( track ) { + if( m_doc->onTheFly() ) { + // this is only supported by cdrecord versions >= 2.01a13 + writer->addArgument( QFile::encodeName( m_tempData->infFileName( track ) ) ); + } + else { + writer->addArgument( QFile::encodeName( m_tempData->bufferFileName( track ) ) ); + } + track = track->next(); + } +} + +void K3bMixedJob::addDataTrack( K3bCdrecordWriter* writer ) +{ + // add data track + if( m_usedDataMode == K3b::MODE2 ) { + if( k3bcore->externalBinManager()->binObject("cdrecord") && + k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "xamix" ) ) + writer->addArgument( "-xa" ); + else + writer->addArgument( "-xa1" ); + } + else + writer->addArgument( "-data" ); + + if( m_doc->onTheFly() ) + writer->addArgument( QString("-tsize=%1s").arg(m_isoImager->size()) )->addArgument("-"); + else + writer->addArgument( m_isoImageFilePath ); +} + + +void K3bMixedJob::slotWriterNextTrack( int t, int ) +{ + K3bAudioTrack* track = 0; + + if( m_doc->mixedType() == K3bMixedDoc::DATA_FIRST_TRACK ) { + if( t > 1 ) + track = m_doc->audioDoc()->getTrack(t-1); + } + else if( m_doc->mixedType() == K3bMixedDoc::DATA_LAST_TRACK ) { + if( t < m_doc->audioDoc()->numOfTracks()+1 ) + track = m_doc->audioDoc()->getTrack(t); + } + else if( m_currentAction == WRITING_AUDIO_IMAGE ) + track = m_doc->audioDoc()->getTrack(t); + else + t = m_doc->numOfTracks(); + + if( track ) + emit newSubTask( i18n("Writing track %1 of %2%3") + .arg(t) + .arg(m_doc->numOfTracks()) + .arg( track->title().isEmpty() || track->artist().isEmpty() + ? QString::null + : " (" + track->artist() + " - " + track->title() + ")" ) ); + else + emit newSubTask( i18n("Writing track %1 of %2 (%3)").arg(t).arg(m_doc->numOfTracks()).arg(i18n("ISO9660 data")) ); +} + + +void K3bMixedJob::slotWriterJobPercent( int p ) +{ + double totalTasks = d->copies; + double tasksDone = d->copiesDone; + if( m_doc->audioDoc()->normalize() ) { + totalTasks+=1.0; + tasksDone+=1.0; + } + if( !m_doc->onTheFly() ) { + totalTasks+=1.0; + } + + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + if( m_currentAction == WRITING_AUDIO_IMAGE ) { + // the audio imager has finished in all cases + // the iso imager only if this is not the first copy + if( d->copiesDone > 0 ) + tasksDone += 1.0; + else if( !m_doc->onTheFly() ) + tasksDone += m_audioDocPartOfProcess; + + p = (int)((double)p*m_audioDocPartOfProcess); + } + else { + // all images have been created + if( !m_doc->onTheFly() ) + tasksDone += 1.0; + + p = (int)(100.0*m_audioDocPartOfProcess + (double)p*(1.0-m_audioDocPartOfProcess)); + } + } + else if( !m_doc->onTheFly() ) + tasksDone += 1.0; + + emit percent( (int)((100.0*tasksDone + (double)p) / totalTasks) ); +} + + +void K3bMixedJob::slotAudioDecoderPercent( int p ) +{ + // the only thing finished here might be the isoimager which is part of this task + if( !m_doc->onTheFly() ) { + double totalTasks = d->copies+1; + if( m_doc->audioDoc()->normalize() ) + totalTasks+=1.0; + + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) + p = (int)((double)p*m_audioDocPartOfProcess); + else + p = (int)(100.0*(1.0-m_audioDocPartOfProcess) + (double)p*m_audioDocPartOfProcess); + + emit percent( (int)((double)p / totalTasks) ); + } +} + + +void K3bMixedJob::slotAudioDecoderSubPercent( int p ) +{ + if( !m_doc->onTheFly() ) { + emit subPercent( p ); + } +} + + +void K3bMixedJob::slotIsoImagerPercent( int p ) +{ + if( !m_doc->onTheFly() ) { + emit subPercent( p ); + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + + double totalTasks = d->copies+1.0; + double tasksDone = d->copiesDone; + if( m_doc->audioDoc()->normalize() ) { + totalTasks+=1.0; + // the normalizer finished + tasksDone+=1.0; + } + + // the writing of the audio part finished + tasksDone += m_audioDocPartOfProcess; + + // the audio decoder finished (which is part of this task in terms of progress) + p = (int)(100.0*m_audioDocPartOfProcess + (double)p*(1.0-m_audioDocPartOfProcess)); + + emit percent( (int)((100.0*tasksDone + (double)p) / totalTasks) ); + } + else { + double totalTasks = d->copies+1.0; + if( m_doc->audioDoc()->normalize() ) + totalTasks+=1.0; + + emit percent( (int)((double)(p*(1.0-m_audioDocPartOfProcess)) / totalTasks) ); + } + } +} + + +bool K3bMixedJob::startWriting() +{ + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + if( m_currentAction == WRITING_ISO_IMAGE) { + if( m_doc->dummy() ) + emit newTask( i18n("Simulating second session") ); + else if( d->copies > 1 ) + emit newTask( i18n("Writing second session of copy %1").arg(d->copiesDone+1) ); + else + emit newTask( i18n("Writing second session") ); + } + else { + if( m_doc->dummy() ) + emit newTask( i18n("Simulating first session") ); + else if( d->copies > 1 ) + emit newTask( i18n("Writing first session of copy %1").arg(d->copiesDone+1) ); + else + emit newTask( i18n("Writing first session") ); + } + } + else if( m_doc->dummy() ) + emit newTask( i18n("Simulating") ); + else + emit newTask( i18n("Writing Copy %1").arg(d->copiesDone+1) ); + + + // if we append the second session the cd is already in the drive + if( !(m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION + && m_currentAction == WRITING_ISO_IMAGE) ) { + + emit newSubTask( i18n("Waiting for media") ); + if( waitForMedia( m_doc->burner() ) < 0 ) { + cancel(); + return false; + } + + // just to be sure we did not get canceled during the async discWaiting + if( m_canceled ) + return false; + + // check if the project will fit on the CD + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + // the media is in and has been checked so this should be fast (hopefully) + K3b::Msf mediaSize = m_doc->burner()->diskInfo().capacity(); + if( mediaSize < m_projectSize ) { + if( k3bcore->globalSettings()->overburn() ) { + emit infoMessage( i18n("Trying to write more than the official disk capacity"), K3bJob::WARNING ); + } + else { + emit infoMessage( i18n("Data does not fit on disk."), ERROR ); + return false; + } + } + } + } + + // in case we determined the max possible writing speed we have to reset the speed on the writer job + // here since an inserted media is necessary + // the Max speed job will compare the max speed value with the supported values of the writer + if( d->maxSpeed ) + m_writer->setBurnSpeed( d->maxSpeedJob->maxSpeed() ); + + emit burning(true); + m_writer->start(); + + if( m_doc->onTheFly() ) { + // now the writer is running and we can get it's stdin + // we only use this method when writing on-the-fly since + // we cannot easily change the audioDecode fd while it's working + // which we would need to do since we write into several + // image files. + m_audioImager->writeToFd( m_writer->fd() ); + m_isoImager->writeToFd( m_writer->fd() ); + } + + return true; +} + + +void K3bMixedJob::createIsoImage() +{ + m_currentAction = CREATING_ISO_IMAGE; + + // prepare iso image file + m_isoImageFilePath = m_tempFilePrefix + "_datatrack.iso"; + + if( !m_doc->onTheFly() ) + emit newTask( i18n("Creating ISO image file") ); + emit newSubTask( i18n("Creating ISO image in %1").arg(m_isoImageFilePath) ); + emit infoMessage( i18n("Creating ISO image in %1").arg(m_isoImageFilePath), INFO ); + + m_isoImager->writeToImageFile( m_isoImageFilePath ); + m_isoImager->start(); +} + + +void K3bMixedJob::cleanupAfterError() +{ + m_errorOccuredAndAlreadyReported = true; + // m_audioImager->cancel(); + m_isoImager->cancel(); + if( m_writer ) + m_writer->cancel(); + + if( m_tocFile ) delete m_tocFile; + m_tocFile = 0; + + // remove the temp files + removeBufferFiles(); +} + + +void K3bMixedJob::removeBufferFiles() +{ + if ( !m_doc->onTheFly() ) { + emit infoMessage( i18n("Removing buffer files."), INFO ); + } + + if( QFile::exists( m_isoImageFilePath ) ) + if( !QFile::remove( m_isoImageFilePath ) ) + emit infoMessage( i18n("Could not delete file %1.").arg(m_isoImageFilePath), ERROR ); + + // removes buffer images and temp toc or inf files + m_tempData->cleanup(); +} + + +void K3bMixedJob::determineWritingMode() +{ + // we don't need this when only creating image and it is possible + // that the burn device is null + if( m_doc->onlyCreateImages() ) + return; + + // at first we determine the data mode + // -------------------------------------------------------------- + if( m_doc->dataDoc()->dataMode() == K3b::DATA_MODE_AUTO ) { + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) + m_usedDataMode = K3b::MODE2; + else + m_usedDataMode = K3b::MODE1; + } + else + m_usedDataMode = m_doc->dataDoc()->dataMode(); + + + // we try to use cdrecord if possible + bool cdrecordOnTheFly = false; + bool cdrecordCdText = false; + bool cdrecordUsable = false; + + if( k3bcore->externalBinManager()->binObject("cdrecord") ) { + cdrecordOnTheFly = + k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "audio-stdin" ); + cdrecordCdText = + k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "cdtext" ); + cdrecordUsable = + !( !cdrecordOnTheFly && m_doc->onTheFly() ) && + !( m_doc->audioDoc()->cdText() && !cdrecordCdText ); + } + + // Writing Application + // -------------------------------------------------------------- + // cdrecord seems to have problems writing xa 1 disks in dao mode? At least on my system! + if( writingApp() == K3b::DEFAULT ) { + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + if( m_doc->writingMode() == K3b::DAO || + ( m_doc->writingMode() == K3b::WRITING_MODE_AUTO && !cdrecordUsable ) ) { + m_usedAudioWritingApp = K3b::CDRDAO; + m_usedDataWritingApp = K3b::CDRDAO; + } + else { + m_usedAudioWritingApp = K3b::CDRECORD; + m_usedDataWritingApp = K3b::CDRECORD; + } + } + else { + if( cdrecordUsable ) { + m_usedAudioWritingApp = K3b::CDRECORD; + m_usedDataWritingApp = K3b::CDRECORD; + } + else { + m_usedAudioWritingApp = K3b::CDRDAO; + m_usedDataWritingApp = K3b::CDRDAO; + } + } + } + else { + m_usedAudioWritingApp = writingApp(); + m_usedDataWritingApp = writingApp(); + } + + // TODO: use K3bExceptions::brokenDaoAudio + + // Writing Mode (TAO/DAO/RAW) + // -------------------------------------------------------------- + if( m_doc->writingMode() == K3b::WRITING_MODE_AUTO ) { + + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + if( m_usedDataWritingApp == K3b::CDRECORD ) + m_usedDataWritingMode = K3b::TAO; + else + m_usedDataWritingMode = K3b::DAO; + + // default to Session at once for the audio part + m_usedAudioWritingMode = K3b::DAO; + } + else if( writer()->dao() ) { + m_usedDataWritingMode = K3b::DAO; + m_usedAudioWritingMode = K3b::DAO; + } + else { + m_usedDataWritingMode = K3b::TAO; + m_usedAudioWritingMode = K3b::TAO; + } + } + else { + m_usedAudioWritingMode = m_doc->writingMode(); + m_usedDataWritingMode = m_doc->writingMode(); + } + + + if( m_usedDataWritingApp == K3b::CDRECORD ) { + if( !cdrecordOnTheFly && m_doc->onTheFly() ) { + m_doc->setOnTheFly( false ); + emit infoMessage( i18n("On-the-fly writing with cdrecord < 2.01a13 not supported."), ERROR ); + } + + if( m_doc->audioDoc()->cdText() ) { + if( !cdrecordCdText ) { + m_doc->audioDoc()->writeCdText( false ); + emit infoMessage( i18n("Cdrecord %1 does not support CD-Text writing.").arg(k3bcore->externalBinManager()->binObject("cdrecord")->version), ERROR ); + } + else if( m_usedAudioWritingMode == K3b::TAO ) { + emit infoMessage( i18n("It is not possible to write CD-Text in TAO mode. Try DAO or RAW."), WARNING ); + } + } + } +} + + +void K3bMixedJob::normalizeFiles() +{ + if( !m_normalizeJob ) { + m_normalizeJob = new K3bAudioNormalizeJob( this, this ); + + connect( m_normalizeJob, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_normalizeJob, SIGNAL(percent(int)), this, SLOT(slotNormalizeProgress(int)) ); + connect( m_normalizeJob, SIGNAL(subPercent(int)), this, SLOT(slotNormalizeSubProgress(int)) ); + connect( m_normalizeJob, SIGNAL(finished(bool)), this, SLOT(slotNormalizeJobFinished(bool)) ); + connect( m_normalizeJob, SIGNAL(newTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_normalizeJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + } + + // add all the files + QValueVector files; + K3bAudioTrack* track = m_doc->audioDoc()->firstTrack(); + while( track ) { + files.append( m_tempData->bufferFileName(track) ); + track = track->next(); + } + + m_normalizeJob->setFilesToNormalize( files ); + + emit newTask( i18n("Normalizing volume levels") ); + m_normalizeJob->start(); +} + +void K3bMixedJob::slotNormalizeJobFinished( bool success ) +{ + if( m_canceled || m_errorOccuredAndAlreadyReported ) + return; + + if( success ) { + if( m_doc->mixedType() == K3bMixedDoc::DATA_FIRST_TRACK ) + m_currentAction = WRITING_ISO_IMAGE; + else + m_currentAction = WRITING_AUDIO_IMAGE; + + if( !prepareWriter() || !startWriting() ) { + cleanupAfterError(); + jobFinished(false); + } + } + else { + cleanupAfterError(); + jobFinished(false); + } +} + +void K3bMixedJob::slotNormalizeProgress( int p ) +{ + double totalTasks = d->copies+2.0; + double tasksDone = 0; + + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) { + // the audio imager finished (m_audioDocPartOfProcess*1 task) + // plus the normalize progress + tasksDone = m_audioDocPartOfProcess; + } + else { + // the iso and audio imagers already finished (one task) + // plus the normalize progress + tasksDone = 1.0; + } + + emit percent( (int)((100.0*tasksDone + (double)p) / totalTasks) ); +} + + +void K3bMixedJob::slotNormalizeSubProgress( int p ) +{ + emit subPercent( p ); +} + + +void K3bMixedJob::prepareProgressInformation() +{ + // calculate percentage of audio and data + // this is also used in on-the-fly mode + double ds = (double)m_doc->dataDoc()->length().totalFrames(); + double as = (double)m_doc->audioDoc()->length().totalFrames(); + m_audioDocPartOfProcess = as/(ds+as); +} + + +QString K3bMixedJob::jobDescription() const +{ + if( m_doc->mixedType() == K3bMixedDoc::DATA_SECOND_SESSION ) + return i18n("Writing Enhanced Audio CD") + + ( m_doc->audioDoc()->title().isEmpty() + ? QString::null + : QString( " (%1)" ).arg(m_doc->audioDoc()->title()) ); + else + return i18n("Writing Mixed Mode CD") + + ( m_doc->audioDoc()->title().isEmpty() + ? QString::null + : QString( " (%1)" ).arg(m_doc->audioDoc()->title()) ); +} + + +QString K3bMixedJob::jobDetails() const +{ + return ( i18n("%1 tracks (%2 minutes audio data, %3 ISO9660 data)") + .arg(m_doc->numOfTracks()) + .arg(m_doc->audioDoc()->length().toString()) + .arg(KIO::convertSize(m_doc->dataDoc()->size())) + + ( m_doc->copies() > 1 && !m_doc->dummy() + ? i18n(" - %n copy", " - %n copies", m_doc->copies()) + : QString::null ) ); +} + +#include "k3bmixedjob.moc" diff --git a/libk3b/projects/mixedcd/k3bmixedjob.h b/libk3b/projects/mixedcd/k3bmixedjob.h new file mode 100644 index 0000000..50a1dc7 --- /dev/null +++ b/libk3b/projects/mixedcd/k3bmixedjob.h @@ -0,0 +1,144 @@ +/* + * + * $Id: k3bmixedjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BMIXEDJOB_H +#define K3BMIXEDJOB_H + +#include + + +class K3bMixedDoc; +class K3bIsoImager; +class K3bAudioImager; +class QFile; +class QDataStream; +class K3bAbstractWriter; +class K3bWaveFileWriter; +class KTempFile; +class K3bCdrecordWriter; +class K3bMsInfoFetcher; +class K3bAudioNormalizeJob; +class K3bAudioJobTempData; +class K3bDevice::Device; + +/** + *@author Sebastian Trueg + */ +class K3bMixedJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bMixedJob( K3bMixedDoc*, K3bJobHandler*, QObject* parent = 0 ); + ~K3bMixedJob(); + + K3bDoc* doc() const; + K3bDevice::Device* writer() const; + + QString jobDescription() const; + QString jobDetails() const; + + public slots: + void cancel(); + void start(); + + protected slots: + // iso imager slots + void slotIsoImagerFinished( bool success ); + void slotIsoImagerPercent(int); + + // ms info fetcher slots + void slotMsInfoFetched(bool); + + // audio decoder slots + void slotAudioDecoderFinished( bool ); + void slotAudioDecoderNextTrack( int, int ); + void slotAudioDecoderPercent(int); + void slotAudioDecoderSubPercent( int ); + + // writer slots + void slotWriterFinished( bool success ); + void slotWriterNextTrack(int, int); + void slotWriterJobPercent(int); + + // normalizing slots + void slotNormalizeJobFinished( bool ); + void slotNormalizeProgress( int ); + void slotNormalizeSubProgress( int ); + + // misc slots + void slotMediaReloadedForSecondSession( bool ); + void slotMaxSpeedJobFinished( bool ); + + private: + bool prepareWriter(); + bool writeTocFile(); + bool writeInfFiles(); + bool startWriting(); + void startFirstCopy(); + void addAudioTracks( K3bCdrecordWriter* writer ); + void addDataTrack( K3bCdrecordWriter* writer ); + void cleanupAfterError(); + void removeBufferFiles(); + void createIsoImage(); + void determineWritingMode(); + void normalizeFiles(); + void prepareProgressInformation(); + void writeNextCopy(); + void determinePreliminaryDataImageSize(); + + K3bMixedDoc* m_doc; + K3bIsoImager* m_isoImager; + K3bAudioImager* m_audioImager; + K3bAudioJobTempData* m_tempData; + K3bWaveFileWriter* m_waveFileWriter; + K3bAbstractWriter* m_writer; + K3bMsInfoFetcher* m_msInfoFetcher; + K3bAudioNormalizeJob* m_normalizeJob; + + QString m_isoImageFilePath; + + KTempFile* m_tocFile; + + enum Action { INITIALIZING_IMAGER, + PREPARING_DATA, + CREATING_ISO_IMAGE, + CREATING_AUDIO_IMAGE, + WRITING_ISO_IMAGE, + WRITING_AUDIO_IMAGE, + FETCHING_MSINFO }; + + int m_currentAction; + double m_audioDocPartOfProcess; + + bool m_canceled; + bool m_errorOccuredAndAlreadyReported; + + int m_usedDataMode; + int m_usedDataWritingApp; + int m_usedAudioWritingApp; + int m_usedDataWritingMode; + int m_usedAudioWritingMode; + + QString m_tempFilePrefix; + + K3b::Msf m_projectSize; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/movixcd/Makefile.am b/libk3b/projects/movixcd/Makefile.am new file mode 100644 index 0000000..d1b4f5d --- /dev/null +++ b/libk3b/projects/movixcd/Makefile.am @@ -0,0 +1,23 @@ +# we need the ../datacd for the uic generated header files +AM_CPPFLAGS= -I$(srcdir)/../../core \ + -I$(srcdir)/../../../libk3bdevice \ + -I$(srcdir)/../../../src \ + -I$(srcdir)/../../tools \ + -I$(srcdir)/../datacd \ + -I$(srcdir)/.. \ + -I../datacd \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libmovix.la + +libmovix_la_SOURCES = k3bmovixprogram.cpp \ + k3bmovixdoc.cpp \ + k3bmovixjob.cpp \ + k3bmovixfileitem.cpp \ + k3bmovixdocpreparer.cpp + +include_HEADERS = k3bmovixdoc.h \ + k3bmovixjob.h \ + k3bmovixfileitem.h diff --git a/libk3b/projects/movixcd/k3bmovixdoc.cpp b/libk3b/projects/movixcd/k3bmovixdoc.cpp new file mode 100644 index 0000000..f7b2198 --- /dev/null +++ b/libk3b/projects/movixcd/k3bmovixdoc.cpp @@ -0,0 +1,445 @@ +/* + * + * $Id: k3bmovixdoc.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bmovixdoc.h" +#include "k3bmovixjob.h" +#include "k3bmovixfileitem.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +K3bMovixDoc::K3bMovixDoc( QObject* parent ) + : K3bDataDoc( parent ) +{ + connect( this, SIGNAL(itemRemoved(K3bDataItem*)), + this, SLOT(slotDataItemRemoved(K3bDataItem*)) ); +} + + +K3bMovixDoc::~K3bMovixDoc() +{ +} + + +K3bBurnJob* K3bMovixDoc::newBurnJob( K3bJobHandler* hdl, QObject* parent ) +{ + return new K3bMovixJob( this, hdl, parent ); +} + + +bool K3bMovixDoc::newDocument() +{ + m_loopPlaylist = 1; + m_ejectDisk = false; + m_reboot = false; + m_shutdown = false; + m_randomPlay = false; + + return K3bDataDoc::newDocument(); +} + + +void K3bMovixDoc::addUrls( const KURL::List& urls ) +{ + for( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it ) { + addMovixFile( *it ); + } + + emit newMovixFileItems(); +} + + +void K3bMovixDoc::addMovixFile( const KURL& _url, int pos ) +{ + KURL url = K3b::convertToLocalUrl( _url ); + + QFileInfo f( url.path() ); + if( !f.isFile() || !url.isLocalFile() ) + return; + + QString newName = f.fileName(); + if( nameAlreadyInDir( newName, root() ) ) { + kapp->config()->setGroup("Data project settings"); + bool dropDoubles = kapp->config()->readBoolEntry( "Drop doubles", false ); + if( dropDoubles ) + return; + + bool ok = true; + do { + newName = KInputDialog::getText( i18n("Enter New Filename"), + i18n("A file with that name already exists. Please enter a new name:"), + newName, &ok, 0 ); + } while( ok && nameAlreadyInDir( newName, root() ) ); + + if( !ok ) + return; + } + + K3bMovixFileItem* newK3bItem = new K3bMovixFileItem( f.absFilePath(), this, root(), newName ); + if( pos < 0 || pos > (int)m_movixFiles.count() ) + pos = m_movixFiles.count(); + + m_movixFiles.insert( pos, newK3bItem ); + + emit newMovixFileItems(); + + setModified(true); +} + + +bool K3bMovixDoc::loadDocumentData( QDomElement* rootElem ) +{ + if( !root() ) + newDocument(); + + QDomNodeList nodes = rootElem->childNodes(); + + if( nodes.item(0).nodeName() != "general" ) { + kdDebug() << "(K3bMovixDoc) could not find 'general' section." << endl; + return false; + } + if( !readGeneralDocumentData( nodes.item(0).toElement() ) ) + return false; + + + // parse options + // ----------------------------------------------------------------- + if( nodes.item(1).nodeName() != "data_options" ) { + kdDebug() << "(K3bMovixDoc) could not find 'data_options' section." << endl; + return false; + } + if( !loadDocumentDataOptions( nodes.item(1).toElement() ) ) + return false; + // ----------------------------------------------------------------- + + + + // parse header + // ----------------------------------------------------------------- + if( nodes.item(2).nodeName() != "data_header" ) { + kdDebug() << "(K3bMovixDoc) could not find 'data_header' section." << endl; + return false; + } + if( !loadDocumentDataHeader( nodes.item(2).toElement() ) ) + return false; + // ----------------------------------------------------------------- + + + + // parse movix options + // ----------------------------------------------------------------- + if( nodes.item(3).nodeName() != "movix_options" ) { + kdDebug() << "(K3bMovixDoc) could not find 'movix_options' section." << endl; + return false; + } + + // load the options + QDomNodeList optionList = nodes.item(3).childNodes(); + for( uint i = 0; i < optionList.count(); i++ ) { + + QDomElement e = optionList.item(i).toElement(); + if( e.isNull() ) + return false; + + if( e.nodeName() == "shutdown") + setShutdown( e.attributeNode( "activated" ).value() == "yes" ); + else if( e.nodeName() == "reboot") + setReboot( e.attributeNode( "activated" ).value() == "yes" ); + else if( e.nodeName() == "eject_disk") + setEjectDisk( e.attributeNode( "activated" ).value() == "yes" ); + else if( e.nodeName() == "random_play") + setRandomPlay( e.attributeNode( "activated" ).value() == "yes" ); + else if( e.nodeName() == "no_dma") + setNoDma( e.attributeNode( "activated" ).value() == "yes" ); + else if( e.nodeName() == "subtitle_fontset") + setSubtitleFontset( e.text() ); + else if( e.nodeName() == "boot_message_language") + setBootMessageLanguage( e.text() ); + else if( e.nodeName() == "audio_background") + setAudioBackground( e.text() ); + else if( e.nodeName() == "keyboard_language") + setKeyboardLayout( e.text() ); + else if( e.nodeName() == "codecs") + setCodecs( QStringList::split( ',', e.text() ) ); + else if( e.nodeName() == "default_boot_label") + setDefaultBootLabel( e.text() ); + else if( e.nodeName() == "additional_mplayer_options") + setAdditionalMPlayerOptions( e.text() ); + else if( e.nodeName() == "unwanted_mplayer_options") + setUnwantedMPlayerOptions( e.text() ); + else if( e.nodeName() == "loop_playlist") + setLoopPlaylist( e.text().toInt() ); + else + kdDebug() << "(K3bMovixDoc) unknown movix option: " << e.nodeName() << endl; + } + // ----------------------------------------------------------------- + + // parse files + // ----------------------------------------------------------------- + if( nodes.item(4).nodeName() != "movix_files" ) { + kdDebug() << "(K3bMovixDoc) could not find 'movix_files' section." << endl; + return false; + } + + // load file items + QDomNodeList fileList = nodes.item(4).childNodes(); + for( uint i = 0; i < fileList.count(); i++ ) { + + QDomElement e = fileList.item(i).toElement(); + if( e.isNull() ) + return false; + + if( e.nodeName() == "file" ) { + if( !e.hasAttribute( "name" ) ) { + kdDebug() << "(K3bMovixDoc) found file tag without name attribute." << endl; + return false; + } + + QDomElement urlElem = e.firstChild().toElement(); + if( urlElem.isNull() ) { + kdDebug() << "(K3bMovixDoc) found file tag without url child." << endl; + return false; + } + + // create the item + K3bMovixFileItem* newK3bItem = new K3bMovixFileItem( urlElem.text(), + this, + root(), + e.attributeNode("name").value() ); + m_movixFiles.append( newK3bItem ); + + // subtitle file? + QDomElement subTitleElem = e.childNodes().item(1).toElement(); + if( !subTitleElem.isNull() && subTitleElem.nodeName() == "subtitle_file" ) { + urlElem = subTitleElem.firstChild().toElement(); + if( urlElem.isNull() ) { + kdDebug() << "(K3bMovixDoc) found subtitle_file tag without url child." << endl; + return false; + } + + QString name = K3bMovixFileItem::subTitleFileName( newK3bItem->k3bName() ); + K3bFileItem* subItem = new K3bFileItem( urlElem.text(), this, root(), name ); + newK3bItem->setSubTitleItem( subItem ); + } + } + else { + kdDebug() << "(K3bMovixDoc) found " << e.nodeName() << " node where 'file' was expected." << endl; + return false; + } + } + // ----------------------------------------------------------------- + + + emit newMovixFileItems(); + + return true; +} + + +bool K3bMovixDoc::saveDocumentData( QDomElement* docElem ) +{ + QDomDocument doc = docElem->ownerDocument(); + + saveGeneralDocumentData( docElem ); + + QDomElement optionsElem = doc.createElement( "data_options" ); + saveDocumentDataOptions( optionsElem ); + + QDomElement headerElem = doc.createElement( "data_header" ); + saveDocumentDataHeader( headerElem ); + + QDomElement movixOptElem = doc.createElement( "movix_options" ); + QDomElement movixFilesElem = doc.createElement( "movix_files" ); + + + // save the movix options + QDomElement propElem = doc.createElement( "shutdown" ); + propElem.setAttribute( "activated", shutdown() ? "yes" : "no" ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "reboot" ); + propElem.setAttribute( "activated", reboot() ? "yes" : "no" ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "eject_disk" ); + propElem.setAttribute( "activated", ejectDisk() ? "yes" : "no" ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "random_play" ); + propElem.setAttribute( "activated", randomPlay() ? "yes" : "no" ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "no_dma" ); + propElem.setAttribute( "activated", noDma() ? "yes" : "no" ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "subtitle_fontset" ); + propElem.appendChild( doc.createTextNode( subtitleFontset() ) ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "boot_message_language" ); + propElem.appendChild( doc.createTextNode( bootMessageLanguage() ) ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "audio_background" ); + propElem.appendChild( doc.createTextNode( audioBackground() ) ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "keyboard_language" ); + propElem.appendChild( doc.createTextNode( keyboardLayout() ) ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "codecs" ); + propElem.appendChild( doc.createTextNode( codecs().join(",") ) ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "default_boot_label" ); + propElem.appendChild( doc.createTextNode( defaultBootLabel() ) ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "additional_mplayer_options" ); + propElem.appendChild( doc.createTextNode( additionalMPlayerOptions() ) ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "unwanted_mplayer_options" ); + propElem.appendChild( doc.createTextNode( unwantedMPlayerOptions() ) ); + movixOptElem.appendChild( propElem ); + + propElem = doc.createElement( "loop_playlist" ); + propElem.appendChild( doc.createTextNode( QString::number(loopPlaylist()) ) ); + movixOptElem.appendChild( propElem ); + + + // save the movix items + for( QPtrListIterator it( m_movixFiles ); + *it; ++it ) { + K3bMovixFileItem* item = *it; + + QDomElement topElem = doc.createElement( "file" ); + topElem.setAttribute( "name", item->k3bName() ); + QDomElement urlElem = doc.createElement( "url" ); + urlElem.appendChild( doc.createTextNode( item->localPath() ) ); + topElem.appendChild( urlElem ); + if( item->subTitleItem() ) { + QDomElement subElem = doc.createElement( "subtitle_file" ); + urlElem = doc.createElement( "url" ); + urlElem.appendChild( doc.createTextNode( item->subTitleItem()->localPath() ) ); + subElem.appendChild( urlElem ); + topElem.appendChild( subElem ); + } + + movixFilesElem.appendChild( topElem ); + } + + docElem->appendChild( optionsElem ); + docElem->appendChild( headerElem ); + docElem->appendChild( movixOptElem ); + docElem->appendChild( movixFilesElem ); + + return true; +} + + +void K3bMovixDoc::slotDataItemRemoved( K3bDataItem* item ) +{ + // check if it's a movix item + if( K3bMovixFileItem* fi = dynamic_cast(item) ) + if( m_movixFiles.containsRef( fi ) ) { + emit movixItemRemoved( fi ); + m_movixFiles.removeRef( fi ); + setModified(true); + } +} + + +int K3bMovixDoc::indexOf( K3bMovixFileItem* item ) +{ + return m_movixFiles.findRef(item)+1; +} + + +void K3bMovixDoc::moveMovixItem( K3bMovixFileItem* item, K3bMovixFileItem* itemAfter ) +{ + if( item == itemAfter ) + return; + + // set the current item to track + m_movixFiles.findRef( item ); + // take the current item + item = m_movixFiles.take(); + + // if after == 0 findRef returnes -1 + int pos = m_movixFiles.findRef( itemAfter ); + m_movixFiles.insert( pos+1, item ); + + emit newMovixFileItems(); + + setModified(true); +} + + +void K3bMovixDoc::addSubTitleItem( K3bMovixFileItem* item, const KURL& url ) +{ + if( item->subTitleItem() ) + removeSubTitleItem( item ); + + QFileInfo f( url.path() ); + if( !f.isFile() || !url.isLocalFile() ) + return; + + // check if there already is a file named like we want to name the subTitle file + QString name = K3bMovixFileItem::subTitleFileName( item->k3bName() ); + + if( nameAlreadyInDir( name, root() ) ) { + KMessageBox::error( 0, i18n("Could not rename subtitle file. File with requested name %1 already exists.").arg(name) ); + return; + } + + K3bFileItem* subItem = new K3bFileItem( f.absFilePath(), this, root(), name ); + item->setSubTitleItem( subItem ); + + emit newMovixFileItems(); + + setModified(true); +} + + +void K3bMovixDoc::removeSubTitleItem( K3bMovixFileItem* item ) +{ + if( item->subTitleItem() ) { + emit subTitleItemRemoved( item ); + + delete item->subTitleItem(); + item->setSubTitleItem(0); + + setModified(true); + } +} + +#include "k3bmovixdoc.moc" diff --git a/libk3b/projects/movixcd/k3bmovixdoc.h b/libk3b/projects/movixcd/k3bmovixdoc.h new file mode 100644 index 0000000..53debfc --- /dev/null +++ b/libk3b/projects/movixcd/k3bmovixdoc.h @@ -0,0 +1,125 @@ +/* + * + * $Id: k3bmovixdoc.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_MOVIX_DOC_H_ +#define _K3B_MOVIX_DOC_H_ + + +#include + +#include +#include "k3b_export.h" +//class K3bView; +class KURL; +class QDomElement; +class K3bFileItem; +class K3bMovixFileItem; +class K3bDataItem; +class KConfig; + + +class LIBK3B_EXPORT K3bMovixDoc : public K3bDataDoc +{ + Q_OBJECT + + public: + K3bMovixDoc( QObject* parent = 0 ); + virtual ~K3bMovixDoc(); + + virtual int type() const { return MOVIX; } + + virtual K3bBurnJob* newBurnJob( K3bJobHandler* hdl, QObject* parent ); + + bool newDocument(); + + const QPtrList& movixFileItems() const { return m_movixFiles; } + + int indexOf( K3bMovixFileItem* ); + + + bool shutdown() const { return m_shutdown; } + bool reboot() const { return m_reboot; } + bool ejectDisk() const { return m_ejectDisk; } + bool randomPlay() const { return m_randomPlay; } + const QString& subtitleFontset() const { return m_subtitleFontset; } + const QString& bootMessageLanguage() const { return m_bootMessageLanguage; } + const QString& audioBackground() const { return m_audioBackground; } + const QString& keyboardLayout() const { return m_keyboardLayout; } + const QStringList& codecs() const { return m_codecs; } + const QString& defaultBootLabel() const { return m_defaultBootLabel; } + const QString& additionalMPlayerOptions() const { return m_additionalMPlayerOptions; } + const QString& unwantedMPlayerOptions() const { return m_unwantedMPlayerOptions; } + int loopPlaylist() const { return m_loopPlaylist; } + bool noDma() const { return m_noDma; } + + void setShutdown( bool v ) { m_shutdown = v; } + void setReboot( bool v ) { m_reboot = v; } + void setEjectDisk( bool v ) { m_ejectDisk = v; } + void setRandomPlay( bool v ) { m_randomPlay = v; } + void setSubtitleFontset( const QString& v ) { m_subtitleFontset = v; } + void setBootMessageLanguage( const QString& v ) { m_bootMessageLanguage = v; } + void setAudioBackground( const QString& b ) { m_audioBackground = b; } + void setKeyboardLayout( const QString& l ) { m_keyboardLayout = l; } + void setCodecs( const QStringList& c ) { m_codecs = c; } + void setDefaultBootLabel( const QString& v ) { m_defaultBootLabel = v; } + void setAdditionalMPlayerOptions( const QString& v ) { m_additionalMPlayerOptions = v; } + void setUnwantedMPlayerOptions( const QString& v ) { m_unwantedMPlayerOptions = v; } + void setLoopPlaylist( int v ) { m_loopPlaylist = v; } + void setNoDma( bool b ) { m_noDma = b; } + + signals: + void newMovixFileItems(); + void movixItemRemoved( K3bMovixFileItem* ); + void subTitleItemRemoved( K3bMovixFileItem* ); + + public slots: + void addUrls( const KURL::List& urls ); + void addMovixFile( const KURL& url, int pos = -1 ); + void moveMovixItem( K3bMovixFileItem* item, K3bMovixFileItem* itemAfter ); + void addSubTitleItem( K3bMovixFileItem*, const KURL& ); + void removeSubTitleItem( K3bMovixFileItem* ); + + protected: + /** reimplemented from K3bDoc */ + bool loadDocumentData( QDomElement* root ); + /** reimplemented from K3bDoc */ + bool saveDocumentData( QDomElement* ); + + virtual QString typeString() const { return "movix"; } + + private slots: + void slotDataItemRemoved( K3bDataItem* ); + + private: + QPtrList m_movixFiles; + + bool m_shutdown; + bool m_reboot; + bool m_ejectDisk; + bool m_randomPlay; + QString m_subtitleFontset; + QString m_bootMessageLanguage; + QString m_audioBackground; + QString m_keyboardLayout; + QStringList m_codecs; + QString m_defaultBootLabel; + QString m_additionalMPlayerOptions; + QString m_unwantedMPlayerOptions; + int m_loopPlaylist; + bool m_noDma; +}; + +#endif diff --git a/libk3b/projects/movixcd/k3bmovixdocpreparer.cpp b/libk3b/projects/movixcd/k3bmovixdocpreparer.cpp new file mode 100644 index 0000000..57e18af --- /dev/null +++ b/libk3b/projects/movixcd/k3bmovixdocpreparer.cpp @@ -0,0 +1,490 @@ +/* + * + * $Id: k3bmovixdocpreparer.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bmovixdocpreparer.h" +#include "k3bmovixdoc.h" +#include "k3bmovixprogram.h" +#include "k3bmovixfileitem.h" + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + + +class K3bMovixDocPreparer::Private +{ +public: + Private() + : doc(0), + playlistFile(0), + isolinuxConfigFile(0), + movixRcFile(0), + isolinuxDir(0), + movixDir(0), + mplayerDir(0), + playlistFileItem(0), + structuresCreated(false) { + } + + K3bMovixDoc* doc; + const K3bMovixBin* eMovixBin; + + KTempFile* playlistFile; + KTempFile* isolinuxConfigFile; + KTempFile* movixRcFile; + + K3bDirItem* isolinuxDir; + K3bDirItem* movixDir; + K3bDirItem* mplayerDir; + K3bFileItem* playlistFileItem; + + QPtrList newMovixItems; + + bool structuresCreated; +}; + + +K3bMovixDocPreparer::K3bMovixDocPreparer( K3bMovixDoc* doc, K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bJob( jh, parent, name ) +{ + d = new Private(); + d->doc = doc; +} + + +K3bMovixDocPreparer::~K3bMovixDocPreparer() +{ + removeMovixStructures(); + delete d; +} + + +K3bMovixDoc* K3bMovixDocPreparer::doc() const +{ + return d->doc; +} + + +void K3bMovixDocPreparer::start() +{ + kdDebug() << k_funcinfo << endl; + jobStarted(); + + bool success = true; + if( d->structuresCreated ) + removeMovixStructures(); + else + success = createMovixStructures(); + + jobFinished(success); +} + + +void K3bMovixDocPreparer::cancel() +{ + // do nothing... +} + + +bool K3bMovixDocPreparer::createMovixStructures() +{ + kdDebug() << k_funcinfo << endl; + removeMovixStructures(); + + if( doc() ) { + doc()->setMultiSessionMode( K3bDataDoc::NONE ); + doc()->prepareFilenames(); + } + + d->eMovixBin = dynamic_cast( k3bcore->externalBinManager()->binObject("eMovix") ); + if( d->eMovixBin ) { + bool success = false; + if( d->eMovixBin->version >= K3bVersion( 0, 9, 0 ) ) + success = addMovixFilesNew(); + else + success = addMovixFiles(); + + d->structuresCreated = success; + return success; + } + else { + emit infoMessage( i18n("Could not find a valid eMovix installation."), ERROR ); + return false; + } +} + + +void K3bMovixDocPreparer::removeMovixStructures() +{ + kdDebug() << k_funcinfo << endl; + // remove movix files from doc + // the dataitems do the cleanup in the doc + delete d->movixDir; + delete d->isolinuxDir; + delete d->mplayerDir; + delete d->playlistFileItem; + + d->movixDir = 0; + d->isolinuxDir = 0; + d->mplayerDir = 0; + d->playlistFileItem = 0; + + d->newMovixItems.setAutoDelete( true ); + d->newMovixItems.clear(); + + // remove all the temp files + delete d->playlistFile; + delete d->isolinuxConfigFile; + delete d->movixRcFile; + + d->playlistFile = 0; + d->isolinuxConfigFile = 0; + d->movixRcFile = 0; + + d->structuresCreated = false; +} + + +bool K3bMovixDocPreparer::writePlaylistFile() +{ + delete d->playlistFile; + d->playlistFile = new KTempFile(); + d->playlistFile->setAutoDelete(true); + + if( QTextStream* s = d->playlistFile->textStream() ) { + + const QPtrList& movixFileItems = d->doc->movixFileItems(); + + for( QPtrListIterator it( movixFileItems ); + *it; ++it ) { + *s << "/cdrom/"; + *s << it.current()->writtenName(); + *s << endl; + } + + d->playlistFile->close(); + return true; + } + else { + emit infoMessage( i18n("Could not write to temporary file %1").arg(d->playlistFile->name()), ERROR ); + return false; + } +} + + +bool K3bMovixDocPreparer::writeIsolinuxConfigFile( const QString& originalPath ) +{ + delete d->isolinuxConfigFile; + d->isolinuxConfigFile = new KTempFile(); + d->isolinuxConfigFile->setAutoDelete(true); + + if( QTextStream* s = d->isolinuxConfigFile->textStream() ) { + + // now open the default isolinux.cfg and copy everything except the first line which contains + // the default boot label + QFile f( originalPath ); + if( f.open( IO_ReadOnly ) ) { + + QTextStream isolinuxConfigOrig( &f ); + + if( d->doc->defaultBootLabel() != i18n("default") ) { + isolinuxConfigOrig.readLine(); // skip first line + *s << "default " << d->doc->defaultBootLabel() << endl; + } + + QString line = isolinuxConfigOrig.readLine(); + while( !line.isNull() ) { + *s << line << endl; + line = isolinuxConfigOrig.readLine(); + } + + d->isolinuxConfigFile->close(); + return true; + } + else + return false; + } + else { + emit infoMessage( i18n("Could not write to temporary file %1").arg(d->isolinuxConfigFile->name()), ERROR ); + return false; + } +} + + +bool K3bMovixDocPreparer::writeMovixRcFile() +{ + delete d->movixRcFile; + d->movixRcFile = new KTempFile(); + d->movixRcFile->setAutoDelete(true); + + if( QTextStream* s = d->movixRcFile->textStream() ) { + + if( !d->doc->additionalMPlayerOptions().isEmpty() ) + *s << "extra-mplayer-options=" << d->doc->additionalMPlayerOptions() << endl; + if( !d->doc->unwantedMPlayerOptions().isEmpty() ) + *s << "unwanted-mplayer-options=" << d->doc->unwantedMPlayerOptions() << endl; + *s << "loop=" << d->doc->loopPlaylist() << endl; + if( d->doc->shutdown() ) + *s << "shut=y" << endl; + if( d->doc->reboot() ) + *s << "reboot=y" << endl; + if( d->doc->ejectDisk() ) + *s << "eject=y" << endl; + if( d->doc->randomPlay() ) + *s << "random=y" << endl; + if( d->doc->noDma() ) + *s << "dma=n" << endl; + + d->movixRcFile->close(); + return true; + } + else { + emit infoMessage( i18n("Could not write to temporary file %1").arg(d->movixRcFile->name()), ERROR ); + return false; + } +} + + +bool K3bMovixDocPreparer::addMovixFiles() +{ + // first of all we create the directories + d->isolinuxDir = new K3bDirItem( "isolinux", d->doc, d->doc->root() ); + d->movixDir = new K3bDirItem( "movix", d->doc, d->doc->root() ); + K3bDirItem* kernelDir = d->doc->addEmptyDir( "kernel", d->isolinuxDir ); + + // add the linux kernel + (void)new K3bFileItem( d->eMovixBin->path + "/isolinux/kernel/vmlinuz", d->doc, kernelDir ); + + // add the boot image + K3bBootItem* bootItem = d->doc->createBootItem( d->eMovixBin->path + "/isolinux/isolinux.bin", + d->isolinuxDir ); + bootItem->setImageType( K3bBootItem::NONE ); + bootItem->setLoadSize( 4 ); + bootItem->setBootInfoTable(true); + + // some sort weights as defined in isolinux + d->isolinuxDir->setSortWeight( 100 ); + kernelDir->setSortWeight( 50 ); + bootItem->setSortWeight( 200 ); + + // rename the boot catalog file + d->doc->bootCataloge()->setK3bName( "isolinux.boot" ); + + // the following sucks! Redesign it! + + // add all the isolinux files + QStringList isolinuxFiles = d->eMovixBin->isolinuxFiles(); + isolinuxFiles.remove( "isolinux.bin" ); + isolinuxFiles.remove( "isolinux.cfg" ); + isolinuxFiles.remove( "kernel/vmlinuz" ); + for( QStringList::const_iterator it = isolinuxFiles.begin(); + it != isolinuxFiles.end(); ++it ) { + QString path = d->eMovixBin->path + "/isolinux/" + *it; + (void)new K3bFileItem( path, d->doc, d->isolinuxDir ); + } + + const QStringList& movixFiles = d->eMovixBin->movixFiles(); + for( QStringList::const_iterator it = movixFiles.begin(); + it != movixFiles.end(); ++it ) { + QString path = d->eMovixBin->path + "/movix/" + *it; + (void)new K3bFileItem( path, d->doc, d->movixDir ); + } + + // add doku files + QString path = d->eMovixBin->languageDir( d->doc->bootMessageLanguage() ); + QDir dir(path); + QStringList helpFiles = dir.entryList(QDir::Files); + for( QStringList::const_iterator it = helpFiles.begin(); + it != helpFiles.end(); ++it ) { + // some emovix installations include backup-files, no one's perfect ;) + if( !(*it).endsWith( "~" ) ) + (void)new K3bFileItem( path + "/" + *it, d->doc, d->isolinuxDir ); + } + + + // add subtitle font dir + if( !d->doc->subtitleFontset().isEmpty() && + d->doc->subtitleFontset() != i18n("none") ) { + d->mplayerDir = new K3bDirItem( "mplayer", d->doc, d->doc->root() ); + + QString fontPath = d->eMovixBin->subtitleFontDir( d->doc->subtitleFontset() ); + QFileInfo fontType( fontPath ); + if( fontType.isDir() ) { + K3bDirItem* fontDir = new K3bDirItem( "font", d->doc, d->mplayerDir ); + QDir dir( fontPath ); + QStringList fontFiles = dir.entryList( QDir::Files ); + for( QStringList::const_iterator it = fontFiles.begin(); + it != fontFiles.end(); ++it ) { + (void)new K3bFileItem( fontPath + "/" + *it, d->doc, fontDir ); + } + } + else { + // just a ttf file + // needs to be named: subfont.ttf and needs to be placed in mplayer/ + // instead of mplayer/font + (void)new K3bFileItem( fontPath, + d->doc, + d->mplayerDir, + "subfont.ttf" ); + } + } + + + // add movix-config-file and boot-config file + if( writeMovixRcFile() && + writeIsolinuxConfigFile( d->eMovixBin->path + "/isolinux/isolinux.cfg" ) && + writePlaylistFile() ) { + + (void)new K3bFileItem( d->movixRcFile->name(), d->doc, d->movixDir, "movixrc" ); + (void)new K3bFileItem( d->isolinuxConfigFile->name(), d->doc, d->isolinuxDir, "isolinux.cfg" ); + d->playlistFileItem = new K3bFileItem( d->playlistFile->name(), d->doc, d->doc->root(), "movix.list" ); + + return true; + } + else + return false; +} + + +bool K3bMovixDocPreparer::addMovixFilesNew() +{ + // 1. get a list of files from the movixbin + // 2. create file items (replace isolinux.cfg with the one created above) + // 3. add movixrc and movix.list files + // 4. set weights for isolinux files + + // FIXME: use the settings from the doc + QStringList files = d->eMovixBin->files( d->doc->keyboardLayout(), + d->doc->subtitleFontset(), + d->doc->audioBackground(), + d->doc->bootMessageLanguage(), + "all" /*d->doc->codecs()*/ ); // for now we simply don't allow selection + + for( QStringList::iterator it = files.begin(); it != files.end(); ++it ) { + QString docPath = (*it).section( ' ', 0, 0 ); + QString filePath = (*it).section( ' ', 1, 1 ); + QString fileName = filePath.section( '/', -1 ); + + if( fileName == "isolinux.cfg" ) { + // replace the local file with our modified one + if( writeIsolinuxConfigFile( filePath ) ) + createItem( d->isolinuxConfigFile->name(), docPath )->setK3bName( "isolinux.cfg" ); + else + return false; + } + else if( fileName == "isolinux.bin" ) { + // create boot item (no need to remember this since it's in a dir which will be removed + // anyway) + K3bBootItem* bootItem = d->doc->createBootItem( filePath, createDir(docPath) ); + bootItem->setImageType( K3bBootItem::NONE ); + bootItem->setLoadSize( 4 ); + bootItem->setBootInfoTable(true); + + // set the proper sort weight + bootItem->setSortWeight( 200 ); + bootItem->parent()->setSortWeight( 100 ); + } + else if( fileName != "movixrc" ) { // we create our own movixrc + K3bFileItem* item = createItem( filePath, docPath ); + + // Truetype subtitle fonts needs to be named subfont.ttf + if( fileName == d->doc->subtitleFontset() + ".ttf" ) { + item->setK3bName( "subfont.ttf" ); + } + else if( fileName == "vmlinuz" ) + item->setSortWeight( 50 ); + } + } + + // Some distributions (such as Gentoo for example) do use the win32codecs package instead of the + // eMovix supplied codecs. These codecs are not picked up by the movix-conf script + K3bDirItem* codecDir = dynamic_cast( d->doc->root()->findByPath( "/eMoviX/codecs" ) ); + if( !codecDir || codecDir->isEmpty() ) { + QDir localCodecDir( d->eMovixBin->movixDataDir() + "/codecs" ); + if( localCodecDir.exists() ) { + QStringList codecFiles = localCodecDir.entryList( QDir::Files ); + for( QStringList::const_iterator it = codecFiles.begin(); it != codecFiles.end(); ++it ) + createItem( localCodecDir.path() + '/' + *it, "/eMoviX/codecs" ); + } + } + + if( writePlaylistFile() && writeMovixRcFile() ) { + // add the two items that are not listed by the script + createItem( d->movixRcFile->name(), "/eMoviX/movix" )->setK3bName( "movixrc" ); + createItem( d->playlistFile->name(), "/" )->setK3bName( "movix.list" ); + return true; + } + else + return false; +} + + +K3bFileItem* K3bMovixDocPreparer::createItem( const QString& localPath, const QString& docPath ) +{ + // make sure the path in the doc exists + K3bDirItem* dir = createDir( docPath ); + + // create the file in dir + K3bFileItem* item = new K3bFileItem( localPath, d->doc, dir ); + + // remember the item to remove it becasue the dir cannot be removed + if( dir == d->doc->root() ) + d->newMovixItems.append( item ); + + return item; +} + + +K3bDirItem* K3bMovixDocPreparer::createDir( const QString& docPath ) +{ + QStringList docPathSections = QStringList::split( '/', docPath ); + K3bDirItem* dir = d->doc->root(); + for( QStringList::iterator it = docPathSections.begin(); it != docPathSections.end(); ++it ) { + K3bDataItem* next = dir->find( *it ); + if( !next ) + dir = new K3bDirItem( *it, d->doc, dir ); + else if( next->isDir() ) + dir = static_cast( next ); + else { + kdError() << "(K3bMovixDocPreparer) found non-dir item where a dir was needed." << endl; + return 0; + } + } + + // remember the dir to remove it + if( dir != d->doc->root() ) { + K3bDirItem* delDir = dir; + while( delDir->parent() != d->doc->root() ) + delDir = delDir->parent(); + if( d->newMovixItems.findRef( delDir ) == -1 ) + d->newMovixItems.append( delDir ); + } + + return dir; +} + +#include "k3bmovixdocpreparer.moc" diff --git a/libk3b/projects/movixcd/k3bmovixdocpreparer.h b/libk3b/projects/movixcd/k3bmovixdocpreparer.h new file mode 100644 index 0000000..3844eae --- /dev/null +++ b/libk3b/projects/movixcd/k3bmovixdocpreparer.h @@ -0,0 +1,67 @@ +/* + * + * $Id: k3bmovixdocpreparer.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_MOVIX_DOC_PREPARER_H_ +#define _K3B_MOVIX_DOC_PREPARER_H_ + +#include + +class K3bMovixDoc; +class K3bFileItem; +class K3bDirItem; + + +/** + * This class creates the needed eMovix structures in an eMovix doc + * and removes them after creating the image. + */ +class K3bMovixDocPreparer : public K3bJob +{ + Q_OBJECT + + public: + explicit K3bMovixDocPreparer( K3bMovixDoc* doc, K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bMovixDocPreparer(); + + K3bMovixDoc* doc() const; + + bool createMovixStructures(); + void removeMovixStructures(); + + public slots: + /** + * use createMovixStructures and removeMovixStructures instead. + */ + void start(); + + /** + * Useless since this job works syncronously + */ + void cancel(); + + private: + bool writePlaylistFile(); + bool writeIsolinuxConfigFile( const QString& ); + bool writeMovixRcFile(); + bool addMovixFiles(); + bool addMovixFilesNew(); + K3bFileItem* createItem( const QString& localPath, const QString& docPath ); + K3bDirItem* createDir( const QString& docPath ); + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/movixcd/k3bmovixfileitem.cpp b/libk3b/projects/movixcd/k3bmovixfileitem.cpp new file mode 100644 index 0000000..12803a2 --- /dev/null +++ b/libk3b/projects/movixcd/k3bmovixfileitem.cpp @@ -0,0 +1,68 @@ +/* + * + * $Id: k3bmovixfileitem.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bmovixfileitem.h" +#include "k3bmovixdoc.h" + +#include + + +K3bMovixFileItem::K3bMovixFileItem( const QString& fileName, + K3bMovixDoc* doc, + K3bDirItem* dir, + const QString& k3bName ) + : K3bFileItem( fileName, doc, dir, k3bName ), + m_doc(doc), + m_subTitleItem(0) +{ +} + + +K3bMovixFileItem::~K3bMovixFileItem() +{ + if( m_subTitleItem ) + m_doc->removeSubTitleItem( this ); + + // remove this from parentdir + // it is important to do it here and not + // rely on the K3bFileItem destructor becasue + // otherwise the doc is not informed early enough + if( parent() ) + parent()->takeDataItem( this ); +} + + +void K3bMovixFileItem::setK3bName( const QString& newName ) +{ + K3bFileItem::setK3bName( newName ); + + // take care of the subTitle file + if( m_subTitleItem ) { + m_subTitleItem->setK3bName( subTitleFileName(k3bName()) ); + } +} + + +QString K3bMovixFileItem::subTitleFileName( const QString& name ) +{ + // remove ending from k3bName + QString subName = name; + int pos = subName.findRev("."); + if( pos > 0 ) + subName.truncate( pos ); + subName += ".sub"; + return subName; +} diff --git a/libk3b/projects/movixcd/k3bmovixfileitem.h b/libk3b/projects/movixcd/k3bmovixfileitem.h new file mode 100644 index 0000000..343f00b --- /dev/null +++ b/libk3b/projects/movixcd/k3bmovixfileitem.h @@ -0,0 +1,52 @@ +/* + * + * $Id: k3bmovixfileitem.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_MOVIX_FILEITEM_H_ +#define _K3B_MOVIX_FILEITEM_H_ + +#include + +class K3bMovixDoc; + + +class K3bMovixFileItem : public K3bFileItem +{ + public: + K3bMovixFileItem( const QString& fileName, K3bMovixDoc* doc, K3bDirItem* dir, const QString& k3bName = 0 ); + ~K3bMovixFileItem(); + + K3bFileItem* subTitleItem() const { return m_subTitleItem; } + void setSubTitleItem( K3bFileItem* i ) { m_subTitleItem = i; } + + /** + * reimplemented from K3bDataItem + * also renames the subTitleItem + */ + void setK3bName( const QString& ); + + /** + * returnes the name that the subtitle file must have in + * order to work with mplayer + */ + static QString subTitleFileName( const QString& ); + + private: + K3bMovixDoc* m_doc; + + K3bFileItem* m_subTitleItem; +}; + +#endif diff --git a/libk3b/projects/movixcd/k3bmovixjob.cpp b/libk3b/projects/movixcd/k3bmovixjob.cpp new file mode 100644 index 0000000..2579453 --- /dev/null +++ b/libk3b/projects/movixcd/k3bmovixjob.cpp @@ -0,0 +1,132 @@ +/* + * + * $Id: k3bmovixjob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bmovixjob.h" +#include "k3bmovixdoc.h" +#include "k3bmovixfileitem.h" +#include "k3bmovixdocpreparer.h" + +#include +#include +#include + +#include +#include + + +K3bMovixJob::K3bMovixJob( K3bMovixDoc* doc, K3bJobHandler* jh, QObject* parent ) + : K3bBurnJob( jh, parent ), + m_doc(doc) +{ + m_dataJob = new K3bDataJob( doc, this, this ); + m_movixDocPreparer = new K3bMovixDocPreparer( doc, this, this ); + + // pipe signals + connect( m_dataJob, SIGNAL(percent(int)), this, SIGNAL(percent(int)) ); + connect( m_dataJob, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); + connect( m_dataJob, SIGNAL(processedSubSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( m_dataJob, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSize(int, int)) ); + connect( m_dataJob, SIGNAL(bufferStatus(int)), this, SIGNAL(bufferStatus(int)) ); + connect( m_dataJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); + connect( m_dataJob, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + connect( m_dataJob, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) ); + connect( m_dataJob, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_dataJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + connect( m_dataJob, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_dataJob, SIGNAL(burning(bool)), this, SIGNAL(burning(bool)) ); + + // we need to clean up here + connect( m_dataJob, SIGNAL(finished(bool)), this, SLOT(slotDataJobFinished(bool)) ); + + connect( m_movixDocPreparer, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); +} + + +K3bMovixJob::~K3bMovixJob() +{ +} + + +K3bDevice::Device* K3bMovixJob::writer() const +{ + return m_dataJob->writer(); +} + + +K3bDoc* K3bMovixJob::doc() const +{ + return m_doc; +} + + +void K3bMovixJob::start() +{ + jobStarted(); + + m_canceled = false; + m_dataJob->setWritingApp( writingApp() ); + + if( m_movixDocPreparer->createMovixStructures() ) { + m_dataJob->start(); + } + else { + m_movixDocPreparer->removeMovixStructures(); + jobFinished(false); + } +} + + +void K3bMovixJob::cancel() +{ + m_canceled = true; + m_dataJob->cancel(); +} + + +void K3bMovixJob::slotDataJobFinished( bool success ) +{ + m_movixDocPreparer->removeMovixStructures(); + + if( m_canceled || m_dataJob->hasBeenCanceled() ) + emit canceled(); + + jobFinished( success ); +} + + +QString K3bMovixJob::jobDescription() const +{ + if( m_doc->isoOptions().volumeID().isEmpty() ) + return i18n("Writing eMovix CD"); + else + return i18n("Writing eMovix CD (%1)").arg(m_doc->isoOptions().volumeID()); +} + + +QString K3bMovixJob::jobDetails() const +{ + return ( i18n("1 file (%1) and about 8 MB eMovix data", + "%n files (%1) and about 8 MB eMovix data", + m_doc->movixFileItems().count()).arg(KIO::convertSize(m_doc->size())) + + ( m_doc->copies() > 1 + ? i18n(" - %n copy", " - %n copies", m_doc->copies()) + : QString::null ) ); +} + +#include "k3bmovixjob.moc" diff --git a/libk3b/projects/movixcd/k3bmovixjob.h b/libk3b/projects/movixcd/k3bmovixjob.h new file mode 100644 index 0000000..81dea8e --- /dev/null +++ b/libk3b/projects/movixcd/k3bmovixjob.h @@ -0,0 +1,60 @@ +/* + * + * $Id: k3bmovixjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_MOVIX_JOB_H_ +#define _K3B_MOVIX_JOB_H_ + +#include + +class K3bMovixDoc; +class K3bDevice::Device; +class K3bDataJob; +class KTempFile; +class K3bMovixInstallation; +class K3bMovixDocPreparer; +class K3bDirItem; +class K3bFileItem; + +class K3bMovixJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bMovixJob( K3bMovixDoc* doc, K3bJobHandler*, QObject* parent = 0 ); + ~K3bMovixJob(); + + K3bDoc* doc() const; + K3bDevice::Device* writer() const; + + QString jobDescription() const; + QString jobDetails() const; + + public slots: + void start(); + void cancel(); + + private slots: + void slotDataJobFinished( bool ); + + private: + K3bMovixDoc* m_doc; + K3bDataJob* m_dataJob; + K3bMovixDocPreparer* m_movixDocPreparer; + + bool m_canceled; +}; + +#endif diff --git a/libk3b/projects/movixcd/k3bmovixprogram.cpp b/libk3b/projects/movixcd/k3bmovixprogram.cpp new file mode 100644 index 0000000..8720e8d --- /dev/null +++ b/libk3b/projects/movixcd/k3bmovixprogram.cpp @@ -0,0 +1,339 @@ +/* + * + * $Id: k3bmovixprogram.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bmovixprogram.h" + +#include + +#include +#include + +#include +#include +#include + + +K3bMovixProgram::K3bMovixProgram() + : K3bExternalProgram( "eMovix" ) +{ +} + +bool K3bMovixProgram::scan( const QString& p ) +{ + if( p.isEmpty() ) + return false; + + QString path = p; + if( path[path.length()-1] != '/' ) + path.append("/"); + + // first test if we have a version info (eMovix >= 0.8.0pre3) + if( !QFile::exists( path + "movix-version" ) ) + return false; + + K3bMovixBin* bin = 0; + + // + // probe version and data dir + // + KProcess vp, dp; + vp << path + "movix-version"; + dp << path + "movix-conf"; + K3bProcessOutputCollector vout( &vp ), dout( &dp ); + if( vp.start( KProcess::Block, KProcess::AllOutput ) && dp.start( KProcess::Block, KProcess::AllOutput ) ) { + // movix-version just gives us the version number on stdout + if( !vout.output().isEmpty() && !dout.output().isEmpty() ) { + bin = new K3bMovixBin( this ); + bin->version = vout.output().stripWhiteSpace(); + bin->path = path; + bin->m_movixPath = dout.output().stripWhiteSpace(); + } + } + else { + kdDebug() << "(K3bMovixProgram) could not start " << path << "movix-version" << endl; + return false; + } + + if( bin->version >= K3bVersion( 0, 9, 0 ) ) + return scanNewEMovix( bin, path ); + else + return scanOldEMovix( bin, path ); +} + + +bool K3bMovixProgram::scanNewEMovix( K3bMovixBin* bin, const QString& path ) +{ + QStringList files = bin->files(); + for( QStringList::iterator it = files.begin(); + it != files.end(); ++it ) { + if( (*it).contains( "isolinux.cfg" ) ) { + bin->m_supportedBootLabels = determineSupportedBootLabels( QStringList::split( " ", *it )[1] ); + break; + } + } + + // here we simply check for the movix-conf program + if( QFile::exists( path + "movix-conf" ) ) { + bin->addFeature( "newfiles" ); + addBin(bin); + return true; + } + else { + delete bin; + return false; + } +} + + +bool K3bMovixProgram::scanOldEMovix( K3bMovixBin* bin, const QString& path ) +{ + // + // first check if all necessary directories are present + // + QDir dir( bin->movixDataDir() ); + QStringList subdirs = dir.entryList( QDir::Dirs ); + if( !subdirs.contains( "boot-messages" ) ) { + kdDebug() << "(K3bMovixProgram) could not find subdir 'boot-messages'" << endl; + delete bin; + return false; + } + if( !subdirs.contains( "isolinux" ) ) { + kdDebug() << "(K3bMovixProgram) could not find subdir 'isolinux'" << endl; + delete bin; + return false; + } + if( !subdirs.contains( "movix" ) ) { + kdDebug() << "(K3bMovixProgram) could not find subdir 'movix'" << endl; + delete bin; + return false; + } + if( !subdirs.contains( "mplayer-fonts" ) ) { + kdDebug() << "(K3bMovixProgram) could not find subdir 'mplayer-fonts'" << endl; + delete bin; + return false; + } + + + // + // check if we have a version of eMovix which contains the movix-files script + // + if( QFile::exists( path + "movix-files" ) ) { + bin->addFeature( "files" ); + + KProcess p; + K3bProcessOutputCollector out( &p ); + p << bin->path + "movix-files"; + if( p.start( KProcess::Block, KProcess::AllOutput ) ) { + bin->m_movixFiles = QStringList::split( "\n", out.output() ); + } + } + + // + // fallback: to be compatible with 0.8.0rc2 we just add all files in the movix directory + // + if( bin->m_movixFiles.isEmpty() ) { + QDir dir( bin->movixDataDir() + "/movix" ); + bin->m_movixFiles = dir.entryList(QDir::Files); + } + + // + // these files are fixed. That should not be a problem + // since Isolinux is quite stable as far as I know. + // + bin->m_isolinuxFiles.append( "initrd.gz" ); + bin->m_isolinuxFiles.append( "isolinux.bin" ); + bin->m_isolinuxFiles.append( "isolinux.cfg" ); + bin->m_isolinuxFiles.append( "kernel/vmlinuz" ); + bin->m_isolinuxFiles.append( "movix.lss" ); + bin->m_isolinuxFiles.append( "movix.msg" ); + + + // + // check every single necessary file :( + // + for( QStringList::const_iterator it = bin->m_isolinuxFiles.begin(); + it != bin->m_isolinuxFiles.end(); ++it ) { + if( !QFile::exists( bin->movixDataDir() + "/isolinux/" + *it ) ) { + kdDebug() << "(K3bMovixProgram) Could not find file " << *it << endl; + delete bin; + return false; + } + } + + // + // now check the boot-messages languages + // + dir.cd( "boot-messages" ); + bin->m_supportedLanguages = dir.entryList(QDir::Dirs); + bin->m_supportedLanguages.remove("."); + bin->m_supportedLanguages.remove(".."); + bin->m_supportedLanguages.remove("CVS"); // the eMovix makefile stuff seems not perfect ;) + bin->m_supportedLanguages.prepend( i18n("default") ); + dir.cdUp(); + + // + // now check the supported mplayer-fontsets + // FIXME: every font dir needs to contain the "font.desc" file! + // + dir.cd( "mplayer-fonts" ); + bin->m_supportedSubtitleFonts = dir.entryList( QDir::Dirs ); + bin->m_supportedSubtitleFonts.remove("."); + bin->m_supportedSubtitleFonts.remove(".."); + bin->m_supportedSubtitleFonts.remove("CVS"); // the eMovix makefile stuff seems not perfect ;) + // new ttf fonts in 0.8.0rc2 + bin->m_supportedSubtitleFonts += dir.entryList( "*.ttf", QDir::Files ); + bin->m_supportedSubtitleFonts.prepend( i18n("none") ); + dir.cdUp(); + + // + // now check the supported boot labels + // + dir.cd( "isolinux" ); + bin->m_supportedBootLabels = determineSupportedBootLabels( dir.filePath("isolinux.cfg") ); + + // + // This seems to be a valid eMovix installation. :) + // + + addBin(bin); + return true; +} + + +QStringList K3bMovixProgram::determineSupportedBootLabels( const QString& isoConfigFile ) const +{ + QStringList list( i18n("default") ); + + QFile f( isoConfigFile ); + if( !f.open( IO_ReadOnly ) ) { + kdDebug() << "(K3bMovixProgram) could not open file '" << f.name() << "'" << endl; + } + else { + QTextStream fs( &f ); + QString line = fs.readLine(); + while( !line.isNull() ) { + if( line.startsWith( "label" ) ) + list.append( line.mid( 5 ).stripWhiteSpace() ); + + line = fs.readLine(); + } + f.close(); + } + + return list; +} + + +QString K3bMovixBin::subtitleFontDir( const QString& font ) const +{ + if( font == i18n("none" ) ) + return ""; + else if( m_supportedSubtitleFonts.contains( font ) ) + return path + "/mplayer-fonts/" + font; + else + return ""; +} + + +QString K3bMovixBin::languageDir( const QString& lang ) const +{ + if( lang == i18n("default") ) + return languageDir( "en" ); + else if( m_supportedLanguages.contains( lang ) ) + return path + "/boot-messages/" + lang; + else + return ""; +} + + +QStringList K3bMovixBin::supportedSubtitleFonts() const +{ + if( version >= K3bVersion( 0, 9, 0 ) ) + return QStringList( i18n("default") ) += supported( "font" ); + else + return m_supportedSubtitleFonts; +} + + +QStringList K3bMovixBin::supportedLanguages() const +{ + if( version >= K3bVersion( 0, 9, 0 ) ) + return QStringList( i18n("default") ) += supported( "lang" ); + else + return m_supportedLanguages; +} + + +// only used for eMovix >= 0.9.0 +QStringList K3bMovixBin::supportedKbdLayouts() const +{ + return QStringList( i18n("default") ) += supported( "kbd" ); +} + + +// only used for eMovix >= 0.9.0 +QStringList K3bMovixBin::supportedBackgrounds() const +{ + return QStringList( i18n("default") ) += supported( "background" ); +} + + +// only used for eMovix >= 0.9.0 +QStringList K3bMovixBin::supportedCodecs() const +{ + return supported( "codecs" ); +} + + +QStringList K3bMovixBin::supported( const QString& type ) const +{ + KProcess p; + K3bProcessOutputCollector out( &p ); + p << path + "movix-conf" << "--supported=" + type; + if( p.start( KProcess::Block, KProcess::AllOutput ) ) + return QStringList::split( "\n", out.output() ); + else + return QStringList(); +} + + +QStringList K3bMovixBin::files( const QString& kbd, + const QString& font, + const QString& bg, + const QString& lang, + const QStringList& codecs ) const +{ + KProcess p; + K3bProcessOutputCollector out( &p ); + p << path + "movix-conf" << "--files"; + + + if( !kbd.isEmpty() && kbd != i18n("default") ) + p << "--kbd" << kbd; + if( !font.isEmpty() && font != i18n("default") ) + p << "--font" << font; + if( !bg.isEmpty() && bg != i18n("default") ) + p << "--background" << bg; + if( !lang.isEmpty() && lang != i18n("default") ) + p << "--lang" << lang; + if( !codecs.isEmpty() ) + p << "--codecs" << codecs.join( "," ); + + if( p.start( KProcess::Block, KProcess::AllOutput ) ) + return QStringList::split( "\n", out.output() ); + else + return QStringList(); +} diff --git a/libk3b/projects/movixcd/k3bmovixprogram.h b/libk3b/projects/movixcd/k3bmovixprogram.h new file mode 100644 index 0000000..a6a9ac0 --- /dev/null +++ b/libk3b/projects/movixcd/k3bmovixprogram.h @@ -0,0 +1,103 @@ +/* + * + * $Id: k3bmovixprogram.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_MOVIX_PROGRAM_H_ +#define _K3B_MOVIX_PROGRAM_H_ + +#include +#include "k3b_export.h" + +class LIBK3B_EXPORT K3bMovixBin : public K3bExternalBin +{ + public: + K3bMovixBin( K3bExternalProgram* p ) + : K3bExternalBin( p ) { + } + + const QString& movixDataDir() const { return m_movixPath; } + + const QStringList& supportedBootLabels() const { return m_supportedBootLabels; } + QStringList supportedSubtitleFonts() const; + QStringList supportedLanguages() const; + QStringList supportedKbdLayouts() const; + QStringList supportedBackgrounds() const; + QStringList supportedCodecs() const; + + /* + * Unused for eMovix versions 0.9.0 and above + */ + const QStringList& movixFiles() const { return m_movixFiles; } + + /* + * Unused for eMovix versions 0.9.0 and above + */ + const QStringList& isolinuxFiles() const { return m_isolinuxFiles; } + + /** + * returnes empty string if font was not found + * + * Unused for eMovix versions 0.9.0 and above + */ + QString subtitleFontDir( const QString& font ) const; + + /** + * returnes empty string if lang was not found + * + * Unused for eMovix versions 0.9.0 and above + */ + QString languageDir( const QString& lang ) const; + + /** + * Interface for the movix-conf --files interface for + * versions >= 0.9.0 + */ + QStringList files( const QString& kbd = QString::null, + const QString& font = QString::null, + const QString& bg = QString::null, + const QString& lang = QString::null, + const QStringList& codecs = QStringList() ) const; + + private: + QStringList supported( const QString& ) const; + + QString m_movixPath; + QStringList m_movixFiles; + QStringList m_isolinuxFiles; + QStringList m_supportedBootLabels; + QStringList m_supportedSubtitleFonts; + QStringList m_supportedLanguages; + + friend class K3bMovixProgram; +}; + + +class LIBK3B_EXPORT K3bMovixProgram : public K3bExternalProgram +{ + public: + K3bMovixProgram(); + + bool scan( const QString& ); + + bool supportsUserParameters() const { return false; } + + private: + bool scanNewEMovix( K3bMovixBin* bin, const QString& ); + bool scanOldEMovix( K3bMovixBin* bin, const QString& ); + QStringList determineSupportedBootLabels( const QString& ) const; +}; + + + +#endif diff --git a/libk3b/projects/movixdvd/Makefile.am b/libk3b/projects/movixdvd/Makefile.am new file mode 100644 index 0000000..7af7283 --- /dev/null +++ b/libk3b/projects/movixdvd/Makefile.am @@ -0,0 +1,21 @@ +# we need the ../datacd and ../movixcd for the uic generated header files +AM_CPPFLAGS= -I$(srcdir)/../../core \ + -I$(srcdir)/../../../libk3bdevice \ + -I$(srcdir)/../../../src \ + -I$(srcdir)/../../tools \ + -I$(srcdir)/../datadvd \ + -I$(srcdir)/../movixcd \ + -I$(srcdir)/../datacd \ + -I$(srcdir)/.. \ + -I../datacd \ + -I../movixcd \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libmovixdvd.la + +libmovixdvd_la_SOURCES = k3bmovixdvddoc.cpp k3bmovixdvdjob.cpp + +include_HEADERS = k3bmovixdvddoc.h \ + k3bmovixdvdjob.h diff --git a/libk3b/projects/movixdvd/k3bmovixdvddoc.cpp b/libk3b/projects/movixdvd/k3bmovixdvddoc.cpp new file mode 100644 index 0000000..80b8ec2 --- /dev/null +++ b/libk3b/projects/movixdvd/k3bmovixdvddoc.cpp @@ -0,0 +1,36 @@ +/* + * + * $Id: k3bmovixdvddoc.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bmovixdvddoc.h" +#include "k3bmovixdvdjob.h" + +#include + + +K3bMovixDvdDoc::K3bMovixDvdDoc( QObject* parent ) + : K3bMovixDoc( parent ) +{ +} + +K3bMovixDvdDoc::~K3bMovixDvdDoc() +{ +} + +K3bBurnJob* K3bMovixDvdDoc::newBurnJob( K3bJobHandler* hdl, QObject* parent ) +{ + return new K3bMovixDvdJob( this, hdl, parent ); +} + +#include "k3bmovixdvddoc.moc" diff --git a/libk3b/projects/movixdvd/k3bmovixdvddoc.h b/libk3b/projects/movixdvd/k3bmovixdvddoc.h new file mode 100644 index 0000000..85943f0 --- /dev/null +++ b/libk3b/projects/movixdvd/k3bmovixdvddoc.h @@ -0,0 +1,40 @@ +/* + * + * $Id: k3bmovixdvddoc.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_MOVIX_DVD_DOC_H_ +#define _K3B_MOVIX_DVD_DOC_H_ + +#include +#include "k3b_export.h" +class KConfig; + + +class LIBK3B_EXPORT K3bMovixDvdDoc : public K3bMovixDoc +{ + Q_OBJECT + + public: + K3bMovixDvdDoc( QObject* parent = 0 ); + ~K3bMovixDvdDoc(); + + int type() const { return MOVIX_DVD; } + + K3bBurnJob* newBurnJob( K3bJobHandler* hdl, QObject* parent ); + + protected: + QString typeString() const { return "movixdvd"; } +}; + +#endif diff --git a/libk3b/projects/movixdvd/k3bmovixdvdjob.cpp b/libk3b/projects/movixdvd/k3bmovixdvdjob.cpp new file mode 100644 index 0000000..b556997 --- /dev/null +++ b/libk3b/projects/movixdvd/k3bmovixdvdjob.cpp @@ -0,0 +1,131 @@ +/* + * + * $Id: k3bmovixdvdjob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bmovixdvdjob.h" +#include "k3bmovixdvddoc.h" +#include "k3bmovixfileitem.h" +#include "k3bmovixdocpreparer.h" + +#include +#include +#include + +#include +#include + + +K3bMovixDvdJob::K3bMovixDvdJob( K3bMovixDvdDoc* doc, K3bJobHandler* jh, QObject* parent ) + : K3bBurnJob( jh, parent ), + m_doc(doc) +{ + m_dvdJob = new K3bDvdJob( doc, this, this ); + m_movixDocPreparer = new K3bMovixDocPreparer( doc, this, this ); + + // pipe signals + connect( m_dvdJob, SIGNAL(percent(int)), this, SIGNAL(percent(int)) ); + connect( m_dvdJob, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); + connect( m_dvdJob, SIGNAL(processedSubSize(int, int)), this, SIGNAL(processedSubSize(int, int)) ); + connect( m_dvdJob, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSize(int, int)) ); + connect( m_dvdJob, SIGNAL(bufferStatus(int)), this, SIGNAL(bufferStatus(int)) ); + connect( m_dvdJob, SIGNAL(writeSpeed(int, int)), this, SIGNAL(writeSpeed(int, int)) ); + connect( m_dvdJob, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) ); + connect( m_dvdJob, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) ); + connect( m_dvdJob, SIGNAL(debuggingOutput(const QString&, const QString&)), + this, SIGNAL(debuggingOutput(const QString&, const QString&)) ); + connect( m_dvdJob, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); + connect( m_dvdJob, SIGNAL(burning(bool)), this, SIGNAL(burning(bool)) ); + + // we need to clean up here + connect( m_dvdJob, SIGNAL(finished(bool)), this, SLOT(slotDvdJobFinished(bool)) ); + + connect( m_movixDocPreparer, SIGNAL(infoMessage(const QString&, int)), + this, SIGNAL(infoMessage(const QString&, int)) ); +} + + +K3bMovixDvdJob::~K3bMovixDvdJob() +{ +} + + +K3bDevice::Device* K3bMovixDvdJob::writer() const +{ + return m_dvdJob->writer(); +} + + +K3bDoc* K3bMovixDvdJob::doc() const +{ + return m_doc; +} + + +void K3bMovixDvdJob::start() +{ + jobStarted(); + + m_canceled = false; + m_dvdJob->setWritingApp( writingApp() ); + + if( m_movixDocPreparer->createMovixStructures() ) { + m_dvdJob->start(); + } + else { + m_movixDocPreparer->removeMovixStructures(); + jobFinished(false); + } +} + + +void K3bMovixDvdJob::cancel() +{ + m_canceled = true; + m_dvdJob->cancel(); +} + + +void K3bMovixDvdJob::slotDvdJobFinished( bool success ) +{ + m_movixDocPreparer->removeMovixStructures(); + + if( m_canceled || m_dvdJob->hasBeenCanceled() ) + emit canceled(); + + jobFinished( success ); +} + + +QString K3bMovixDvdJob::jobDescription() const +{ + if( m_doc->isoOptions().volumeID().isEmpty() ) + return i18n("Writing eMovix DVD"); + else + return i18n("Writing eMovix DVD (%1)").arg(m_doc->isoOptions().volumeID()); +} + + +QString K3bMovixDvdJob::jobDetails() const +{ + return ( i18n("1 file (%1) and about 8 MB eMovix data", + "%n files (%1) and about 8 MB eMovix data", + m_doc->movixFileItems().count()).arg(KIO::convertSize(m_doc->size())) + + ( m_doc->copies() > 1 + ? i18n(" - %n copy", " - %n copies", m_doc->copies()) + : QString::null ) ); +} + +#include "k3bmovixdvdjob.moc" diff --git a/libk3b/projects/movixdvd/k3bmovixdvdjob.h b/libk3b/projects/movixdvd/k3bmovixdvdjob.h new file mode 100644 index 0000000..2b9ce10 --- /dev/null +++ b/libk3b/projects/movixdvd/k3bmovixdvdjob.h @@ -0,0 +1,60 @@ +/* + * + * $Id: k3bmovixdvdjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_MOVIX_DVD_JOB_H_ +#define _K3B_MOVIX_DVD_JOB_H_ + +#include + +class K3bMovixDvdDoc; +class K3bDevice::Device; +class K3bDvdJob; +class KTempFile; +class K3bMovixInstallation; +class K3bMovixDocPreparer; +class K3bDirItem; +class K3bFileItem; + +class K3bMovixDvdJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bMovixDvdJob( K3bMovixDvdDoc* doc, K3bJobHandler*, QObject* parent = 0 ); + ~K3bMovixDvdJob(); + + K3bDoc* doc() const; + K3bDevice::Device* writer() const; + + QString jobDescription() const; + QString jobDetails() const; + + public slots: + void start(); + void cancel(); + + private slots: + void slotDvdJobFinished( bool ); + + private: + K3bMovixDvdDoc* m_doc; + K3bDvdJob* m_dvdJob; + K3bMovixDocPreparer* m_movixDocPreparer; + + bool m_canceled; +}; + +#endif diff --git a/libk3b/projects/videocd/Makefile.am b/libk3b/projects/videocd/Makefile.am new file mode 100644 index 0000000..1e18d02 --- /dev/null +++ b/libk3b/projects/videocd/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS= -I$(srcdir)/../../core \ + -I$(srcdir)/../../../src \ + -I$(srcdir)/../../../libk3bdevice \ + -I$(srcdir)/../../tools \ + -I$(srcdir)/.. \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libvcd.la + +libvcd_la_SOURCES = k3bvcddoc.cpp k3bvcdtrack.cpp k3bvcdjob.cpp k3bvcdoptions.cpp k3bvcdxmlview.cpp + +libvcd_la_LIBADD = mpeginfo/libmpeginfo.la + +SUBDIRS = cdi extra mpeginfo + +include_HEADERS = k3bvcdjob.h \ + k3bvcddoc.h \ + k3bvcdoptions.h diff --git a/libk3b/projects/videocd/cdi/Makefile.am b/libk3b/projects/videocd/cdi/Makefile.am new file mode 100644 index 0000000..e487acc --- /dev/null +++ b/libk3b/projects/videocd/cdi/Makefile.am @@ -0,0 +1,5 @@ + +cdidir = $(kde_datadir)/k3b/cdi +cdi_DATA = cdi_imag.rtf cdi_text.fnt cdi_vcd.app cdi_vcd.cfg vcd_on_cdi_41.pdf icdia.htm + +EXTRA_DIST = $(cdi_DATA) diff --git a/libk3b/projects/videocd/cdi/cdi_imag.rtf b/libk3b/projects/videocd/cdi/cdi_imag.rtf new file mode 100644 index 0000000..809145f Binary files /dev/null and b/libk3b/projects/videocd/cdi/cdi_imag.rtf differ diff --git a/libk3b/projects/videocd/cdi/cdi_text.fnt b/libk3b/projects/videocd/cdi/cdi_text.fnt new file mode 100644 index 0000000..0dd0e15 Binary files /dev/null and b/libk3b/projects/videocd/cdi/cdi_text.fnt differ diff --git a/libk3b/projects/videocd/cdi/cdi_vcd.app b/libk3b/projects/videocd/cdi/cdi_vcd.app new file mode 100644 index 0000000..ceb31fc Binary files /dev/null and b/libk3b/projects/videocd/cdi/cdi_vcd.app differ diff --git a/libk3b/projects/videocd/cdi/cdi_vcd.cfg b/libk3b/projects/videocd/cdi/cdi_vcd.cfg new file mode 100644 index 0000000..4aed0eb --- /dev/null +++ b/libk3b/projects/videocd/cdi/cdi_vcd.cfg @@ -0,0 +1,12 @@ +CONTROLS=ALL +CURCOL=YELLOW +PSDCURCOL=RED +PSDCURSHAPE=ARROW +CENTRTRACK=2 +AUTOPLAY=AUTO_ON +DUALCHAN=DUAL_ON +TIMECODE_X=64 +TIMECODE_Y=100 +LOTID_X=64 +LOTID_Y=64 +ALBUM=STANDARD \ No newline at end of file diff --git a/libk3b/projects/videocd/cdi/icdia.htm b/libk3b/projects/videocd/cdi/icdia.htm new file mode 100644 index 0000000..cd6c47b --- /dev/null +++ b/libk3b/projects/videocd/cdi/icdia.htm @@ -0,0 +1,12 @@ + + + + +The New International CD-i Association + + + +The New International CD-i Association - http://www.icdia.org + + + diff --git a/libk3b/projects/videocd/cdi/vcd_on_cdi_41.pdf b/libk3b/projects/videocd/cdi/vcd_on_cdi_41.pdf new file mode 100644 index 0000000..cdf4fed Binary files /dev/null and b/libk3b/projects/videocd/cdi/vcd_on_cdi_41.pdf differ diff --git a/libk3b/projects/videocd/extra/Makefile.am b/libk3b/projects/videocd/extra/Makefile.am new file mode 100644 index 0000000..717fa99 --- /dev/null +++ b/libk3b/projects/videocd/extra/Makefile.am @@ -0,0 +1,5 @@ + +extradir = $(kde_datadir)/k3b/extra +extra_DATA = k3bphotovcd.mpg k3bphotosvcd.mpg + +EXTRA_DIST = $(extra_DATA) diff --git a/libk3b/projects/videocd/extra/k3bphotosvcd.mpg b/libk3b/projects/videocd/extra/k3bphotosvcd.mpg new file mode 100644 index 0000000..50156d7 Binary files /dev/null and b/libk3b/projects/videocd/extra/k3bphotosvcd.mpg differ diff --git a/libk3b/projects/videocd/extra/k3bphotovcd.mpg b/libk3b/projects/videocd/extra/k3bphotovcd.mpg new file mode 100644 index 0000000..2ddb69e Binary files /dev/null and b/libk3b/projects/videocd/extra/k3bphotovcd.mpg differ diff --git a/libk3b/projects/videocd/k3bvcddoc.cpp b/libk3b/projects/videocd/k3bvcddoc.cpp new file mode 100644 index 0000000..462aea3 --- /dev/null +++ b/libk3b/projects/videocd/k3bvcddoc.cpp @@ -0,0 +1,894 @@ +/* +* +* $Id: k3bvcddoc.cpp 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2005 Christian Kvasny +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +// QT-includes +#include +#include +#include +#include +#include +#include +#include +#include + +// KDE-includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// K3b-includes +#include "k3bvcddoc.h" +#include "k3bvcdtrack.h" +#include "k3bvcdjob.h" +#include +#include + + +bool desperate_mode = false; +bool preserve_header = false; +bool print_progress = true; +bool aspect_correction = false; +byte forced_sequence_header = 0; + +K3bVcdDoc::K3bVcdDoc( QObject* parent ) + : K3bDoc( parent ) +{ + m_tracks = 0L; + m_vcdOptions = new K3bVcdOptions(); + + m_docType = VCD; + m_vcdType = NONE; + + m_urlAddingTimer = new QTimer( this ); + connect( m_urlAddingTimer, SIGNAL( timeout() ), this, SLOT( slotWorkUrlQueue() ) ); + + // FIXME: remove the newTracks() signal and replace it with the changed signal + connect( this, SIGNAL( newTracks() ), this, SIGNAL( changed() ) ); + connect( this, SIGNAL( trackRemoved( K3bVcdTrack* ) ), this, SIGNAL( changed() ) ); +} + +K3bVcdDoc::~K3bVcdDoc() +{ + if ( m_tracks ) { + m_tracks->setAutoDelete( true ); + delete m_tracks; + } + + delete m_vcdOptions; +} + +bool K3bVcdDoc::newDocument() +{ + if ( m_tracks ) + while ( m_tracks->first() ) + removeTrack( m_tracks->first() ); + else + m_tracks = new QPtrList; + m_tracks->setAutoDelete( false ); + + return K3bDoc::newDocument(); +} + + +QString K3bVcdDoc::name() const +{ + return m_vcdOptions->volumeId(); +} + + +KIO::filesize_t K3bVcdDoc::calcTotalSize() const +{ + unsigned long long sum = 0; + if ( m_tracks ) { + for ( K3bVcdTrack * track = m_tracks->first(); track; track = m_tracks->next() ) { + sum += track->size(); + } + } + return sum; +} + +KIO::filesize_t K3bVcdDoc::size() const +{ + // mode2 -> mode1 int(( n+2047 ) / 2048) * 2352 + // mode1 -> mode2 int(( n+2351 ) / 2352) * 2048 + long tracksize = long( ( calcTotalSize() + 2351 ) / 2352 ) * 2048; + return tracksize + ISOsize(); +} + +KIO::filesize_t K3bVcdDoc::ISOsize() const +{ + // 136000b for vcd iso reseved + long long iso_size = 136000; + if ( vcdOptions() ->CdiSupport() ) { + iso_size += vcdOptions() ->CDIsize(); + } + + return iso_size; +} + +K3b::Msf K3bVcdDoc::length() const +{ + return K3b::Msf( size() / 2048 ); +} + + +bool K3bVcdDoc::isImage( const KURL& url ) +{ + QImage p; + return p.load( QFile::encodeName( url.path() ) ); +} + +void K3bVcdDoc::addUrls( const KURL::List& urls ) +{ + // make sure we add them at the end even if urls are in the queue + addTracks( urls, 99 ); +} + +void K3bVcdDoc::addTracks( const KURL::List& urls, uint position ) +{ + KURL::List::ConstIterator end( urls.end() ); + for ( KURL::List::ConstIterator it = urls.begin(); it != end; ++it ) { + urlsToAdd.enqueue( new PrivateUrlToAdd( K3b::convertToLocalUrl(*it), position++ ) ); + } + + m_urlAddingTimer->start( 0 ); +} + +void K3bVcdDoc::slotWorkUrlQueue() +{ + if ( !urlsToAdd.isEmpty() ) { + PrivateUrlToAdd * item = urlsToAdd.dequeue(); + lastAddedPosition = item->position; + + // append at the end by default + if ( lastAddedPosition > m_tracks->count() ) + lastAddedPosition = m_tracks->count(); + + if ( !item->url.isLocalFile() ) { + kdDebug() << item->url.path() << " no local file" << endl; + return ; + } + + if ( !QFile::exists( item->url.path() ) ) { + kdDebug() << "(K3bVcdDoc) file not found: " << item->url.path() << endl; + m_notFoundFiles.append( item->url.path() ); + return ; + } + + if ( K3bVcdTrack * newTrack = createTrack( item->url ) ) + addTrack( newTrack, lastAddedPosition ); + + delete item; + + emit newTracks(); + } else { + m_urlAddingTimer->stop(); + + emit newTracks(); + + // reorder pbc tracks + setPbcTracks(); + + informAboutNotFoundFiles(); + } +} + +K3bVcdTrack* K3bVcdDoc::createTrack( const KURL& url ) +{ + char filename[ 255 ]; + QString error_string = ""; + strcpy( filename, QFile::encodeName( url.path() ) ); + K3bMpegInfo* Mpeg = new K3bMpegInfo( filename ); + + if ( Mpeg ) { + int mpegVersion = Mpeg->version(); + if ( mpegVersion > 0 ) { + + if ( vcdType() == NONE && mpegVersion < 2 ) { + m_urlAddingTimer->stop(); + setVcdType( vcdTypes( mpegVersion ) ); + vcdOptions() ->setMpegVersion( mpegVersion ); + KMessageBox::information( kapp->mainWidget(), + i18n( "K3b will create a %1 image from the given MPEG " + "files, but these files must already be in %2 " + "format. K3b does not yet resample MPEG files." ) + .arg( i18n( "VCD" ) ) + .arg( i18n( "VCD" ) ), + i18n( "Information" ) ); + m_urlAddingTimer->start( 0 ); + } else if ( vcdType() == NONE ) { + m_urlAddingTimer->stop(); + vcdOptions() ->setMpegVersion( mpegVersion ); + bool force = false; + force = ( KMessageBox::questionYesNo( kapp->mainWidget(), + i18n( "K3b will create a %1 image from the given MPEG " + "files, but these files must already be in %2 " + "format. K3b does not yet resample MPEG files." ) + .arg( i18n( "SVCD" ) ) + .arg( i18n( "SVCD" ) ) + + "\n\n" + + i18n( "Note: Forcing MPEG2 as VCD is not supported by " + "some standalone DVD players." ), + i18n( "Information" ), + KStdGuiItem::ok().text(), + i18n( "Forcing VCD" ) ) == KMessageBox::No ); + if ( force ) { + setVcdType( vcdTypes( 1 ) ); + vcdOptions() ->setAutoDetect( false ); + } else + setVcdType( vcdTypes( mpegVersion ) ); + + m_urlAddingTimer->start( 0 ); + } + + + if ( numOfTracks() > 0 && vcdOptions() ->mpegVersion() != mpegVersion ) { + KMessageBox::error( kapp->mainWidget(), "(" + url.path() + ")\n" + + i18n( "You cannot mix MPEG1 and MPEG2 video files.\nPlease start a new Project for this filetype.\nResample not implemented in K3b yet." ), + i18n( "Wrong File Type for This Project" ) ); + + delete Mpeg; + return 0; + } + + K3bVcdTrack* newTrack = new K3bVcdTrack( m_tracks, url.path() ); + *( newTrack->mpeg_info ) = *( Mpeg->mpeg_info ); + + if ( newTrack->isSegment() && !vcdOptions()->PbcEnabled() ) { + KMessageBox::information( kapp->mainWidget(), + i18n( "PBC (Playback control) enabled.\n" + "Videoplayers can not reach Segments (Mpeg Still Pictures) without Playback control ." ) , + i18n( "Information" ) ); + + vcdOptions()->setPbcEnabled( true ); + } + + // set defaults; + newTrack->setPlayTime( vcdOptions() ->PbcPlayTime() ); + newTrack->setWaitTime( vcdOptions() ->PbcWaitTime() ); + newTrack->setPbcNumKeys( vcdOptions() ->PbcNumkeysEnabled() ); + delete Mpeg; + + // debugging output + newTrack->PrintInfo(); + + return newTrack; + } + } else if ( isImage( url ) ) { // image track + // woking on ... + // for future use + // photoalbum starts here + // return here the new photoalbum track + } + + if ( Mpeg ) { + error_string = Mpeg->error_string(); + delete Mpeg; + } + + // error (unsupported files) + KMessageBox::error( kapp->mainWidget(), "(" + url.path() + ")\n" + + i18n( "Only MPEG1 and MPEG2 video files are supported.\n" ) + error_string , + i18n( "Wrong File Format" ) ); + + + return 0; +} + +void K3bVcdDoc::addTrack( const KURL& url, uint position ) +{ + urlsToAdd.enqueue( new PrivateUrlToAdd( url, position ) ); + + m_urlAddingTimer->start( 0 ); +} + + +void K3bVcdDoc::addTrack( K3bVcdTrack* track, uint position ) +{ + if ( m_tracks->count() >= 98 ) { + kdDebug() << "(K3bVcdDoc) VCD Green Book only allows 98 tracks." << endl; + // TODO: show some messagebox + delete track; + return ; + } + + lastAddedPosition = position; + + if ( !m_tracks->insert( position, track ) ) { + lastAddedPosition = m_tracks->count(); + m_tracks->insert( m_tracks->count(), track ); + } + + if ( track->isSegment() ) + vcdOptions() ->increaseSegments( ); + else + vcdOptions() ->increaseSequence( ); + + emit newTracks(); + + setModified( true ); +} + + +void K3bVcdDoc::removeTrack( K3bVcdTrack* track ) +{ + if ( !track ) { + return ; + } + + // set the current item to track + if ( m_tracks->findRef( track ) >= 0 ) { + // take the current item + track = m_tracks->take(); + + // remove all pbc references to us? + if ( track->hasRevRef() ) + track->delRefToUs(); + + // remove all pbc references from us? + track->delRefFromUs(); + + // emit signal before deleting the track to avoid crashes + // when the view tries to call some of the tracks' methods + emit trackRemoved( track ); + + if ( track->isSegment() ) + vcdOptions() ->decreaseSegments( ); + else + vcdOptions() ->decreaseSequence( ); + + delete track; + + if ( numOfTracks() == 0 ) { + setVcdType( NONE ); + vcdOptions() ->setAutoDetect( true ); + } + + // reorder pbc tracks + setPbcTracks(); + } +} + +void K3bVcdDoc::moveTrack( const K3bVcdTrack* track, const K3bVcdTrack* after ) +{ + if ( track == after ) + return ; + + // set the current item to track + m_tracks->findRef( track ); + // take the current item + track = m_tracks->take(); + + // if after == 0 findRef returnes -1 + int pos = m_tracks->findRef( after ); + m_tracks->insert( pos + 1, track ); + + // reorder pbc tracks + setPbcTracks(); + + emit changed(); +} + + +QString K3bVcdDoc::typeString() const +{ + return "vcd"; +} + + +K3bBurnJob* K3bVcdDoc::newBurnJob( K3bJobHandler* hdl, QObject* parent ) +{ + return new K3bVcdJob( this, hdl, parent ); +} + +void K3bVcdDoc::informAboutNotFoundFiles() +{ + if ( !m_notFoundFiles.isEmpty() ) { + KMessageBox::informationList( view(), i18n( "Could not find the following files:" ), + m_notFoundFiles, i18n( "Not Found" ) ); + + m_notFoundFiles.clear(); + } +} + +void K3bVcdDoc::setVcdType( int type ) +{ + m_vcdType = type; + switch ( type ) { + case 0: + //vcd 1.1 + vcdOptions() ->setVcdClass( "vcd" ); + vcdOptions() ->setVcdVersion( "1.1" ); + break; + case 1: + //vcd 2.0 + vcdOptions() ->setVcdClass( "vcd" ); + vcdOptions() ->setVcdVersion( "2.0" ); + break; + case 2: + //svcd 1.0 + vcdOptions() ->setVcdClass( "svcd" ); + vcdOptions() ->setVcdVersion( "1.0" ); + break; + case 3: + //hqvcd 1.0 + vcdOptions() ->setVcdClass( "hqvcd" ); + vcdOptions() ->setVcdVersion( "1.0" ); + break; + + } +} + +void K3bVcdDoc::setPbcTracks() +{ + // reorder pbc tracks + /* + if ( !vcdOptions()->PbcEnabled() ) + return; + */ + + if ( m_tracks ) { + int count = m_tracks->count(); + kdDebug() << QString( "K3bVcdDoc::setPbcTracks() - we have %1 tracks in list." ).arg( count ) << endl; + + QPtrListIterator iterTrack( *m_tracks ); + K3bVcdTrack* track; + while ( ( track = iterTrack.current() ) != 0 ) { + ++iterTrack; + for ( int i = 0; i < K3bVcdTrack::_maxPbcTracks; i++ ) { + // do not change userdefined tracks + if ( !track->isPbcUserDefined( i ) ) { + if ( track->getPbcTrack( i ) ) + track->getPbcTrack( i ) ->delFromRevRefList( track ); + + K3bVcdTrack* t = 0L; + int index = track->index(); + + // we are the last track + if ( index == count - 1 ) { + switch ( i ) { + case K3bVcdTrack::PREVIOUS: + // we are not alone :) + if ( count > 1 ) { + t = at( index - 1 ); + t->addToRevRefList( track ); + track->setPbcTrack( i, t ); + } else { + track->setPbcTrack( i ); + track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND ); + } + break; + case K3bVcdTrack::AFTERTIMEOUT: + case K3bVcdTrack::NEXT: + track->setPbcTrack( i ); + track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND ); + break; + case K3bVcdTrack::RETURN: + track->setPbcTrack( i ); + track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND ); + break; + case K3bVcdTrack::DEFAULT: + track->setPbcTrack( i ); + track->setPbcNonTrack( i, K3bVcdTrack::DISABLED ); + break; + } + } + // we are the first track + else if ( index == 0 ) { + switch ( i ) { + case K3bVcdTrack::PREVIOUS: + track->setPbcTrack( i ); + track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND ); + break; + case K3bVcdTrack::AFTERTIMEOUT: + case K3bVcdTrack::NEXT: + t = at( index + 1 ); + t->addToRevRefList( track ); + track->setPbcTrack( i, t ); + break; + case K3bVcdTrack::RETURN: + track->setPbcTrack( i ); + track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND ); + break; + case K3bVcdTrack::DEFAULT: + track->setPbcTrack( i ); + track->setPbcNonTrack( i, K3bVcdTrack::DISABLED ); + break; + } + } + // we are one of the other tracks and have PREVIOUS and NEXT Track + else { + switch ( i ) { + case K3bVcdTrack::PREVIOUS: + t = at( index - 1 ); + t->addToRevRefList( track ); + track->setPbcTrack( i, t ); + break; + case K3bVcdTrack::AFTERTIMEOUT: + case K3bVcdTrack::NEXT: + t = at( index + 1 ); + t->addToRevRefList( track ); + track->setPbcTrack( i, t ); + break; + case K3bVcdTrack::RETURN: + track->setPbcTrack( i ); + track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND ); + break; + case K3bVcdTrack::DEFAULT: + track->setPbcTrack( i ); + track->setPbcNonTrack( i, K3bVcdTrack::DISABLED ); + break; + } + } + } + } + } + } +} + + +bool K3bVcdDoc::loadDocumentData( QDomElement* root ) +{ + newDocument(); + + QDomNodeList nodes = root->childNodes(); + + if ( nodes.length() < 3 ) + return false; + + if ( nodes.item( 0 ).nodeName() != "general" ) + return false; + if ( !readGeneralDocumentData( nodes.item( 0 ).toElement() ) ) + return false; + + if ( nodes.item( 1 ).nodeName() != "vcd" ) + return false; + + if ( nodes.item( 2 ).nodeName() != "contents" ) + return false; + + + // vcd Label + QDomNodeList vcdNodes = nodes.item( 1 ).childNodes(); + + for ( uint i = 0; i < vcdNodes.count(); i++ ) { + QDomNode item = vcdNodes.item( i ); + QString name = item.nodeName(); + + kdDebug() << QString( "(K3bVcdDoc::loadDocumentData) nodeName = '%1'" ).arg( name ) << endl; + + if ( name == "volumeId" ) + vcdOptions() ->setVolumeId( item.toElement().text() ); + else if ( name == "albumId" ) + vcdOptions() ->setAlbumId( item.toElement().text() ); + else if ( name == "volumeSetId" ) + vcdOptions() ->setVolumeSetId( item.toElement().text() ); + else if ( name == "preparer" ) + vcdOptions() ->setPreparer( item.toElement().text() ); + else if ( name == "publisher" ) + vcdOptions() ->setPublisher( item.toElement().text() ); + else if ( name == "vcdType" ) + setVcdType( vcdTypes( item.toElement().text().toInt() ) ); + else if ( name == "mpegVersion" ) + vcdOptions() ->setMpegVersion( item.toElement().text().toInt() ); + else if ( name == "PreGapLeadout" ) + vcdOptions() ->setPreGapLeadout( item.toElement().text().toInt() ); + else if ( name == "PreGapTrack" ) + vcdOptions() ->setPreGapTrack( item.toElement().text().toInt() ); + else if ( name == "FrontMarginTrack" ) + vcdOptions() ->setFrontMarginTrack( item.toElement().text().toInt() ); + else if ( name == "RearMarginTrack" ) + vcdOptions() ->setRearMarginTrack( item.toElement().text().toInt() ); + else if ( name == "FrontMarginTrackSVCD" ) + vcdOptions() ->setFrontMarginTrackSVCD( item.toElement().text().toInt() ); + else if ( name == "RearMarginTrackSVCD" ) + vcdOptions() ->setRearMarginTrackSVCD( item.toElement().text().toInt() ); + else if ( name == "volumeCount" ) + vcdOptions() ->setVolumeCount( item.toElement().text().toInt() ); + else if ( name == "volumeNumber" ) + vcdOptions() ->setVolumeNumber( item.toElement().text().toInt() ); + else if ( name == "AutoDetect" ) + vcdOptions() ->setAutoDetect( item.toElement().text().toInt() ); + else if ( name == "CdiSupport" ) + vcdOptions() ->setCdiSupport( item.toElement().text().toInt() ); + else if ( name == "NonCompliantMode" ) + vcdOptions() ->setNonCompliantMode( item.toElement().text().toInt() ); + else if ( name == "Sector2336" ) + vcdOptions() ->setSector2336( item.toElement().text().toInt() ); + else if ( name == "UpdateScanOffsets" ) + vcdOptions() ->setUpdateScanOffsets( item.toElement().text().toInt() ); + else if ( name == "RelaxedAps" ) + vcdOptions() ->setRelaxedAps( item.toElement().text().toInt() ); + else if ( name == "UseGaps" ) + vcdOptions() ->setUseGaps( item.toElement().text().toInt() ); + else if ( name == "PbcEnabled" ) + vcdOptions() ->setPbcEnabled( item.toElement().text().toInt() ); + else if ( name == "SegmentFolder" ) + vcdOptions() ->setSegmentFolder( item.toElement().text().toInt() ); + else if ( name == "Restriction" ) + vcdOptions() ->setRestriction( item.toElement().text().toInt() ); + } + + // vcd Tracks + QDomNodeList trackNodes = nodes.item( 2 ).childNodes(); + + for ( uint i = 0; i < trackNodes.length(); i++ ) { + + // check if url is available + QDomElement trackElem = trackNodes.item( i ).toElement(); + QString url = trackElem.attributeNode( "url" ).value(); + if ( !QFile::exists( url ) ) + m_notFoundFiles.append( url ); + else { + KURL k; + k.setPath( url ); + if ( K3bVcdTrack * track = createTrack( k ) ) { + track ->setPlayTime( trackElem.attribute( "playtime", "1" ).toInt() ); + track ->setWaitTime( trackElem.attribute( "waittime", "2" ).toInt() ); + track ->setReactivity( trackElem.attribute( "reactivity", "0" ).toInt() ); + track -> setPbcNumKeys( ( trackElem.attribute( "numkeys", "yes" ).contains( "yes" ) ) ? true : false ); + track -> setPbcNumKeysUserdefined( ( trackElem.attribute( "userdefinednumkeys", "no" ).contains( "yes" ) ) ? true : false ); + + addTrack( track, m_tracks->count() ); + } + } + } + + emit newTracks(); + + // do not add saved pbcTrack links when one ore more files missing. + // TODO: add info message to informAboutNotFoundFiles(); + if ( m_notFoundFiles.isEmpty() ) { + int type; + int val; + bool pbctrack; + for ( uint trackId = 0; trackId < trackNodes.length(); trackId++ ) { + QDomElement trackElem = trackNodes.item( trackId ).toElement(); + QDomNodeList trackNodes = trackElem.childNodes(); + for ( uint i = 0; i < trackNodes.length(); i++ ) { + QDomElement trackElem = trackNodes.item( i ).toElement(); + QString name = trackElem.tagName(); + if ( name.contains( "pbc" ) ) { + if ( trackElem.hasAttribute ( "type" ) ) { + type = trackElem.attribute ( "type" ).toInt(); + if ( trackElem.hasAttribute ( "pbctrack" ) ) { + pbctrack = ( trackElem.attribute ( "pbctrack" ) == "yes" ); + if ( trackElem.hasAttribute ( "val" ) ) { + val = trackElem.attribute ( "val" ).toInt(); + K3bVcdTrack* track = m_tracks->at( trackId ); + K3bVcdTrack* pbcTrack = m_tracks->at( val ); + if ( pbctrack ) { + pbcTrack->addToRevRefList( track ); + track->setPbcTrack( type, pbcTrack ); + track->setUserDefined( type, true ); + } else { + track->setPbcTrack( type ); + track->setPbcNonTrack( type, val ); + track->setUserDefined( type, true ); + } + } + } + } + } else if ( name.contains( "numkeys" ) ) { + if ( trackElem.hasAttribute ( "key" ) ) { + int key = trackElem.attribute ( "key" ).toInt(); + if ( trackElem.hasAttribute ( "val" ) ) { + int val = trackElem.attribute ( "val" ).toInt() - 1; + K3bVcdTrack* track = m_tracks->at( trackId ); + if ( val >= 0 ) { + K3bVcdTrack * numkeyTrack = m_tracks->at( val ); + track->setDefinedNumKey( key, numkeyTrack ); + } else { + track->setDefinedNumKey( key, 0L ); + } + } + } + } + + } + + } + setPbcTracks(); + setModified( false ); + } + + informAboutNotFoundFiles(); + return true; +} + + + +bool K3bVcdDoc::saveDocumentData( QDomElement * docElem ) +{ + QDomDocument doc = docElem->ownerDocument(); + saveGeneralDocumentData( docElem ); + + // save Vcd Label + QDomElement vcdMain = doc.createElement( "vcd" ); + + QDomElement vcdElem = doc.createElement( "volumeId" ); + vcdElem.appendChild( doc.createTextNode( vcdOptions() ->volumeId() ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "albumId" ); + vcdElem.appendChild( doc.createTextNode( vcdOptions() ->albumId() ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "volumeSetId" ); + vcdElem.appendChild( doc.createTextNode( vcdOptions() ->volumeSetId() ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "preparer" ); + vcdElem.appendChild( doc.createTextNode( vcdOptions() ->preparer() ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "publisher" ); + vcdElem.appendChild( doc.createTextNode( vcdOptions() ->publisher() ) ); + vcdMain.appendChild( vcdElem ); + + // applicationId() + // systemId() + + vcdElem = doc.createElement( "vcdType" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdType() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "mpegVersion" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->mpegVersion() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "PreGapLeadout" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->PreGapLeadout() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "PreGapTrack" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->PreGapTrack() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "FrontMarginTrack" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->FrontMarginTrack() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "RearMarginTrack" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->RearMarginTrack() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "FrontMarginTrackSVCD" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->FrontMarginTrackSVCD() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "RearMarginTrackSVCD" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->RearMarginTrackSVCD() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "volumeCount" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->volumeCount() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "volumeNumber" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->volumeNumber() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "AutoDetect" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->AutoDetect() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "CdiSupport" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->CdiSupport() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "NonCompliantMode" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->NonCompliantMode() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "Sector2336" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->Sector2336() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "UpdateScanOffsets" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->UpdateScanOffsets() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "RelaxedAps" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->RelaxedAps() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "UseGaps" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->UseGaps() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "PbcEnabled" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->PbcEnabled() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "SegmentFolder" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->SegmentFolder() ) ) ); + vcdMain.appendChild( vcdElem ); + + vcdElem = doc.createElement( "Restriction" ); + vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->Restriction() ) ) ); + vcdMain.appendChild( vcdElem ); + + docElem->appendChild( vcdMain ); + + // save the tracks + // ------------------------------------------------------------- + QDomElement contentsElem = doc.createElement( "contents" ); + + QPtrListIterator iterTrack( *m_tracks ); + K3bVcdTrack* track; + + while ( ( track = iterTrack.current() ) != 0 ) { + ++iterTrack; + + QDomElement trackElem = doc.createElement( "track" ); + trackElem.setAttribute( "url", KIO::decodeFileName( track->absPath() ) ); + trackElem.setAttribute( "playtime", track->getPlayTime() ); + trackElem.setAttribute( "waittime", track->getWaitTime() ); + trackElem.setAttribute( "reactivity", track->Reactivity() ); + trackElem.setAttribute( "numkeys", ( track->PbcNumKeys() ) ? "yes" : "no" ); + trackElem.setAttribute( "userdefinednumkeys", ( track->PbcNumKeysUserdefined() ) ? "yes" : "no" ); + + for ( int i = 0; + i < K3bVcdTrack::_maxPbcTracks; + i++ ) { + if ( track->isPbcUserDefined( i ) ) { + // save pbcTracks + QDomElement pbcElem = doc.createElement( "pbc" ); + pbcElem.setAttribute( "type", i ); + if ( track->getPbcTrack( i ) ) { + pbcElem.setAttribute( "pbctrack", "yes" ); + pbcElem.setAttribute( "val", track->getPbcTrack( i ) ->index() ); + } else { + pbcElem.setAttribute( "pbctrack", "no" ); + pbcElem.setAttribute( "val", track->getNonPbcTrack( i ) ); + } + trackElem.appendChild( pbcElem ); + } + } + QMap numKeyMap = track->DefinedNumKey(); + QMap::const_iterator trackIt; + + for ( trackIt = numKeyMap.begin(); + trackIt != numKeyMap.end(); + ++trackIt ) { + QDomElement numElem = doc.createElement( "numkeys" ); + if ( trackIt.data() ) { + numElem.setAttribute( "key", trackIt.key() ); + numElem.setAttribute( "val", trackIt.data() ->index() + 1 ); + } else { + numElem.setAttribute( "key", trackIt.key() ); + numElem.setAttribute( "val", 0 ); + } + trackElem.appendChild( numElem ); + } + + contentsElem.appendChild( trackElem ); + } + // ------------------------------------------------------------- + + docElem->appendChild( contentsElem ); + + return true; +} + +#include "k3bvcddoc.moc" diff --git a/libk3b/projects/videocd/k3bvcddoc.h b/libk3b/projects/videocd/k3bvcddoc.h new file mode 100644 index 0000000..8b10837 --- /dev/null +++ b/libk3b/projects/videocd/k3bvcddoc.h @@ -0,0 +1,192 @@ +/* +* +* $Id: k3bvcddoc.h 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +#ifndef K3BVCDDOC_H +#define K3BVCDDOC_H + +// Qt Includes +#include +#include +#include +#include +#include +#include +#include + +// Kde Includes +#include + +// K3b Includes +#include "k3bvcdoptions.h" +#include "mpeginfo/k3bmpeginfo.h" +#include +#include "k3b_export.h" +class K3bApp; +class K3bVcdTrack; +class K3bVcdJob; +//class K3bView; +class QWidget; +class QTimer; +class QDomDocument; +class QDomElement; +class KConfig; + + + +class LIBK3B_EXPORT K3bVcdDoc : public K3bDoc +{ + Q_OBJECT + + public: + K3bVcdDoc( QObject* ); + ~K3bVcdDoc(); + + int type() const { return VCD; } + + QString name() const; + + enum vcdTypes { VCD11, VCD20, SVCD10, HQVCD, NONE}; + + bool newDocument(); + int numOfTracks() const + { + return m_tracks->count(); + } + + const QString& vcdImage() const + { + return m_vcdImage; + } + void setVcdImage( const QString& s ) + { + m_vcdImage = s; + } + + K3bVcdTrack* first() + { + return m_tracks->first(); + } + K3bVcdTrack* current() const + { + return m_tracks->current(); + } + K3bVcdTrack* next() + { + return m_tracks->next(); + } + K3bVcdTrack* prev() + { + return m_tracks->prev(); + } + K3bVcdTrack* at( uint i ) + { + return m_tracks->at( i ); + } + K3bVcdTrack* take( uint i ) + { + return m_tracks->take( i ); + } + + const QPtrList* tracks() const + { + return m_tracks; + } + + /** get the current size of the project */ + KIO::filesize_t size() const; + K3b::Msf length() const; + + K3bBurnJob* newBurnJob( K3bJobHandler* hdl, QObject* parent ); + K3bVcdOptions* vcdOptions() const + { + return m_vcdOptions; + } + + int vcdType() const + { + return m_vcdType; + } + void setVcdType( int type ); + void setPbcTracks(); + + public slots: + /** + * will test the file and add it to the project. + * connect to at least result() to know when + * the process is finished and check error() + * to know about the result. + **/ + void addUrls( const KURL::List& ); + void addTrack( const KURL&, uint ); + void addTracks( const KURL::List&, uint ); + /** adds a track without any testing */ + void addTrack( K3bVcdTrack* track, uint position = 0 ); + + // --- TODO: this should read: removeTrack( K3bVcdTrack* ) + void removeTrack( K3bVcdTrack* ); + void moveTrack( const K3bVcdTrack* track, const K3bVcdTrack* after ); + + protected slots: + /** processes queue "urlsToAdd" **/ + void slotWorkUrlQueue(); + + signals: + void newTracks(); + + void trackRemoved( K3bVcdTrack* ); + + protected: + /** reimplemented from K3bDoc */ + bool loadDocumentData( QDomElement* root ); + /** reimplemented from K3bDoc */ + bool saveDocumentData( QDomElement* ); + + QString typeString() const; + + private: + K3bVcdTrack* createTrack( const KURL& url ); + void informAboutNotFoundFiles(); + + QStringList m_notFoundFiles; + QString m_vcdImage; + + class PrivateUrlToAdd + { + public: + PrivateUrlToAdd( const KURL& u, int _pos ) + : url( u ), position( _pos ) + {} + KURL url; + int position; + }; + + /** Holds all the urls that have to be added to the list of tracks. **/ + QPtrQueue urlsToAdd; + QTimer* m_urlAddingTimer; + + QPtrList* m_tracks; + KIO::filesize_t calcTotalSize() const; + KIO::filesize_t ISOsize() const; + + bool isImage( const KURL& url ); + + K3bVcdTrack* m_lastAddedTrack; + K3bVcdOptions* m_vcdOptions; + + int m_vcdType; + uint lastAddedPosition; +}; + +#endif diff --git a/libk3b/projects/videocd/k3bvcdjob.cpp b/libk3b/projects/videocd/k3bvcdjob.cpp new file mode 100644 index 0000000..a1b347a --- /dev/null +++ b/libk3b/projects/videocd/k3bvcdjob.cpp @@ -0,0 +1,567 @@ +/* +* +* $Id: k3bvcdjob.cpp 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "k3bvcdjob.h" + +// K3b Includes +#include "k3bvcddoc.h" +#include "k3bvcdtrack.h" +#include "k3bvcdxmlview.h" +#include +#include +#include +#include +#include +#include +#include +#include + +K3bVcdJob::K3bVcdJob( K3bVcdDoc* doc, K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bBurnJob( jh, parent, name ) +{ + m_doc = doc; + m_doc->setCopies( m_doc->dummy() || m_doc->onlyCreateImages() ? 1 : m_doc->copies() ); + m_process = 0; + m_currentWrittenTrackNumber = 0; + m_bytesFinishedTracks = 0; + m_writerJob = 0; + // m_createimageonlypercent = 33.3; + m_createimageonlypercent = 100 / ( m_doc->copies() + 2 ); + m_currentcopy = 1; + m_imageFinished = false; +} + + +K3bVcdJob::~K3bVcdJob() +{ + delete m_process; + + if ( m_writerJob ) + delete m_writerJob; +} + + +K3bDoc* K3bVcdJob::doc() const +{ + return m_doc; +} + + +K3bDevice::Device* K3bVcdJob::writer() const +{ + if( doc()->onlyCreateImages() ) + return 0; + else + return doc() ->burner(); +} + +void K3bVcdJob::cancel() +{ + cancelAll(); + + emit canceled(); + jobFinished( false ); +} + + +void K3bVcdJob::cancelAll() +{ + m_canceled = true; + + if ( m_writerJob ) + m_writerJob->cancel(); + + if ( m_process->isRunning() ) { + m_process->disconnect( this ); + m_process->kill(); + } + + // remove bin-file if it is unfinished or the user selected to remove image + if ( QFile::exists( m_doc->vcdImage() ) ) { + if ( !m_doc->onTheFly() && m_doc->removeImages() || !m_imageFinished ) { + emit infoMessage( i18n( "Removing Binary file %1" ).arg( m_doc->vcdImage() ), K3bJob::SUCCESS ); + QFile::remove + ( m_doc->vcdImage() ); + m_doc->setVcdImage( "" ); + } + } + + // remove cue-file if it is unfinished or the user selected to remove image + if ( QFile::exists( m_cueFile ) ) { + if ( !m_doc->onTheFly() && m_doc->removeImages() || !m_imageFinished ) { + emit infoMessage( i18n( "Removing Cue file %1" ).arg( m_cueFile ), K3bJob::SUCCESS ); + QFile::remove + ( m_cueFile ); + m_cueFile = ""; + } + } +} + + +void K3bVcdJob::start() +{ + kdDebug() << "(K3bVcdJob) starting job" << endl; + + jobStarted(); + emit burning( false ); + m_canceled = false; + + int pos = QString( m_doc->vcdImage() ).find( ".bin", QString( m_doc->vcdImage() ).length() - 4 ); + if ( pos > 0 ) { + m_cueFile = m_doc->vcdImage().left( pos ) + ".cue"; + } else { + m_cueFile = m_doc->vcdImage() + ".cue"; + m_doc->setVcdImage( m_doc->vcdImage() + ".bin" ); + } + + if ( vcdDoc() ->onlyCreateImages() ) + m_createimageonlypercent = 50.0; + + // vcdxGen(); + xmlGen(); +} + +void K3bVcdJob::xmlGen() +{ + + KTempFile tempF; + m_xmlFile = tempF.name(); + tempF.unlink(); + + K3bVcdXmlView xmlView( m_doc ); + + if ( !xmlView.write( m_xmlFile ) ) { + kdDebug() << "(K3bVcdJob) could not write xmlfile." << endl; + emit infoMessage( i18n( "Could not write correct XML-file." ), K3bJob::ERROR ); + cancelAll(); + jobFinished( false ); + } + + // emit infoMessage( i18n( "XML-file successfully created" ), K3bJob::SUCCESS ); + emit debuggingOutput( "K3bVcdXml:", xmlView.xmlString() ); + + vcdxBuild(); + +} + +void K3bVcdJob::vcdxBuild() +{ + emit newTask( i18n( "Creating image files" ) ); + + m_stage = stageUnknown; + firstTrack = true; + delete m_process; + m_process = new K3bProcess(); + + emit infoMessage( i18n( "Creating Cue/Bin files ..." ), K3bJob::INFO ); + const K3bExternalBin* bin = k3bcore ->externalBinManager() ->binObject( "vcdxbuild" ); + if ( !bin ) { + kdDebug() << "(K3bVcdJob) could not find vcdxbuild executable" << endl; + emit infoMessage( i18n( "Could not find %1 executable." ).arg( "vcdxbuild" ), K3bJob::ERROR ); + emit infoMessage( i18n( "To create VideoCDs you must install VcdImager Version %1." ).arg( ">= 0.7.12" ), K3bJob::INFO ); + emit infoMessage( i18n( "You can find this on your distribution disks or download it from http://www.vcdimager.org" ), K3bJob::INFO ); + cancelAll(); + jobFinished( false ); + return ; + } + + if ( bin->version < K3bVersion( "0.7.12" ) ) { + kdDebug() << "(K3bVcdJob) vcdxbuild executable too old!" << endl; + emit infoMessage( i18n( "%1 executable too old: need version %2 or greater." ).arg( "Vcdxbuild" ).arg( "0.7.12" ), K3bJob::ERROR ); + emit infoMessage( i18n( "You can find this on your distribution disks or download it from http://www.vcdimager.org" ), K3bJob::INFO ); + cancelAll(); + jobFinished( false ); + return ; + } + + if ( !bin->copyright.isEmpty() ) + emit infoMessage( i18n( "Using %1 %2 - Copyright (C) %3" ).arg( bin->name() ).arg( bin->version ).arg( bin->copyright ), INFO ); + + *m_process << bin; + + // additional user parameters from config + const QStringList& params = k3bcore->externalBinManager() ->program( "vcdxbuild" ) ->userParameters(); + for ( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) + *m_process << *it; + + + if ( vcdDoc() ->vcdOptions() ->Sector2336() ) { + kdDebug() << "(K3bVcdJob) Write 2336 Sectors = on" << endl; + *m_process << "--sector-2336"; + } + + *m_process << "--progress" << "--gui"; + + *m_process << QString( "--cue-file=%1" ).arg( m_cueFile ); + + *m_process << QString( "--bin-file=%1" ).arg( m_doc->vcdImage() ); + + *m_process << QString( "%1" ).arg( QFile::encodeName( m_xmlFile ) ); + + connect( m_process, SIGNAL( receivedStderr( KProcess*, char*, int ) ), + this, SLOT( slotParseVcdxBuildOutput( KProcess*, char*, int ) ) ); + connect( m_process, SIGNAL( receivedStdout( KProcess*, char*, int ) ), + this, SLOT( slotParseVcdxBuildOutput( KProcess*, char*, int ) ) ); + connect( m_process, SIGNAL( processExited( KProcess* ) ), + this, SLOT( slotVcdxBuildFinished() ) ); + + // vcdxbuild commandline parameters + kdDebug() << "***** vcdxbuild parameters:" << endl; + ; + const QValueList& args = m_process->args(); + QString s; + for ( QValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { + s += *it + " "; + } + kdDebug() << s << flush << endl; + emit debuggingOutput( "vcdxbuild command:", s ); + + if ( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) { + kdDebug() << "(K3bVcdJob) could not start vcdxbuild" << endl; + emit infoMessage( i18n( "Could not start %1." ).arg( "vcdxbuild" ), K3bJob::ERROR ); + cancelAll(); + jobFinished( false ); + } +} + +void K3bVcdJob::slotParseVcdxBuildOutput( KProcess*, char* output, int len ) +{ + QString buffer = QString::fromLocal8Bit( output, len ); + + // split to lines + QStringList lines = QStringList::split( "\n", buffer ); + + QDomDocument xml_doc; + QDomElement xml_root; + + // do every line + for ( QStringList::Iterator str = lines.begin(); str != lines.end(); ++str ) { + *str = ( *str ).stripWhiteSpace(); + + emit debuggingOutput( "vcdxbuild", *str ); + + xml_doc.setContent( QString( "" ) + *str + "" ); + + xml_root = xml_doc.documentElement(); + + // There should be only one... but ... + for ( QDomNode node = xml_root.firstChild(); !node.isNull(); node = node.nextSibling() ) { + QDomElement el = node.toElement(); + if ( el.isNull() ) + continue; + + const QString tagName = el.tagName().lower(); + + if ( tagName == "progress" ) { + const QString oper = el.attribute( "operation" ).lower(); + const unsigned long long pos = el.attribute( "position" ).toLong(); + const long long size = el.attribute( "size" ).toLong(); + + if ( oper == "scan" ) { + // Scan Video Files + if ( m_stage == stageUnknown || pos < m_bytesFinished ) { + const uint index = el.attribute( "id" ).replace( QRegExp( "sequence-" ), "" ).toUInt(); + + m_currentWrittenTrack = m_doc->at( m_currentWrittenTrackNumber ); + emit newSubTask( i18n( "Scanning video file %1 of %2 (%3)" ).arg( index + 1 ).arg( doc() ->numOfTracks() ).arg( m_currentWrittenTrack->fileName() ) ); + m_bytesFinished = 0; + + if ( !firstTrack ) { + m_bytesFinishedTracks += m_doc->at( m_currentWrittenTrackNumber ) ->size(); + m_currentWrittenTrackNumber++; + } else + firstTrack = false; + } + emit subPercent( ( int ) ( 100.0 * ( double ) pos / ( double ) size ) ); + emit processedSubSize( pos / 1024 / 1024, size / 1024 / 1024 ); + + // this is the first of three processes. + double relOverallWritten = ( ( double ) m_bytesFinishedTracks + ( double ) pos ) / ( double ) doc() ->size(); + emit percent( ( int ) ( m_createimageonlypercent * relOverallWritten ) ); + + m_bytesFinished = pos; + m_stage = stageScan; + + } else if ( oper == "write" ) { + emit subPercent( ( int ) ( 100.0 * ( double ) pos / ( double ) size ) ); + emit processedSubSize( ( pos * 2048 ) / 1024 / 1024, ( size * 2048 ) / 1024 / 1024 ); + emit percent( ( int ) ( m_createimageonlypercent + ( m_createimageonlypercent * ( double ) pos / ( double ) size ) ) ); + + m_stage = stageWrite; + } else { + return ; + } + } else if ( tagName == "log" ) { + QDomText tel = el.firstChild().toText(); + const QString level = el.attribute( "level" ).lower(); + if ( tel.isText() ) { + const QString text = tel.data(); + if ( m_stage == stageWrite && level == "information" ) + kdDebug() << QString( "(K3bVcdJob) VcdxBuild information, %1" ).arg( text ) << endl; + if ( ( text ).startsWith( "writing track" ) ) + emit newSubTask( i18n( "Creating Image for track %1" ).arg( ( text ).mid( 14 ) ) ); + else { + if ( level != "error" ) { + kdDebug() << QString( "(K3bVcdJob) vcdxbuild warning, %1" ).arg( text ) << endl; + parseInformation( text ); + } else { + kdDebug() << QString( "(K3bVcdJob) vcdxbuild error, %1" ).arg( text ) << endl; + emit infoMessage( text, K3bJob::ERROR ); + } + } + } + } + } + } +} + + +void K3bVcdJob::slotVcdxBuildFinished() +{ + if ( m_process->normalExit() ) { + // TODO: check the process' exitStatus() + switch ( m_process->exitStatus() ) { + case 0: + emit infoMessage( i18n( "Cue/Bin files successfully created." ), K3bJob::SUCCESS ); + m_imageFinished = true; + break; + default: + emit infoMessage( i18n( "%1 returned an unknown error (code %2)." ).arg( "vcdxbuild" ).arg( m_process->exitStatus() ), + K3bJob::ERROR ); + emit infoMessage( i18n( "Please send me an email with the last output." ), K3bJob::ERROR ); + cancelAll(); + jobFinished( false ); + return ; + } + } else { + emit infoMessage( i18n( "%1 did not exit cleanly." ).arg( "Vcdxbuild" ), K3bJob::ERROR ); + cancelAll(); + jobFinished( false ); + return ; + } + + //remove xml-file + if ( QFile::exists( m_xmlFile ) ) + QFile::remove + ( m_xmlFile ); + + kdDebug() << QString( "(K3bVcdJob) create only image: %1" ).arg( vcdDoc() ->onlyCreateImages() ) << endl; + if ( !vcdDoc() ->onlyCreateImages() ) + startWriterjob(); + else + jobFinished( true ); +} + +void K3bVcdJob::startWriterjob() +{ + kdDebug() << QString( "(K3bVcdJob) writing copy %1 of %2" ).arg( m_currentcopy ).arg( m_doc->copies() ) << endl; + if ( prepareWriterJob() ) { + if ( waitForMedia( m_doc->burner() ) < 0 ) { + cancel(); + return ; + } + // just to be sure we did not get canceled during the async discWaiting + if ( m_canceled ) + return ; + + if ( m_doc->copies() > 1 ) + emit newTask( i18n( "Writing Copy %1 of %2" ).arg( m_currentcopy ).arg( m_doc->copies() ) ); + + emit burning( true ); + m_writerJob->start(); + } +} + +bool K3bVcdJob::prepareWriterJob() +{ + if ( m_writerJob ) + delete m_writerJob; + + const K3bExternalBin* cdrecordBin = k3bcore->externalBinManager() ->binObject( "cdrecord" ); + if ( writingApp() == K3b::DEFAULT && cdrecordBin->hasFeature( "cuefile" ) && m_doc->burner() ->dao() ) + setWritingApp( K3b::CDRECORD ); + + if ( writingApp() == K3b::CDRDAO || writingApp() == K3b::DEFAULT ) { + K3bCdrdaoWriter * writer = new K3bCdrdaoWriter( m_doc->burner(), this, this ); + // create cdrdao job + writer->setCommand( K3bCdrdaoWriter::WRITE ); + writer->setSimulate( m_doc->dummy() ); + writer->setBurnSpeed( m_doc->speed() ); + + writer->setTocFile( m_cueFile ); + + m_writerJob = writer; + + } else if ( writingApp() == K3b::CDRECORD ) { + K3bCdrecordWriter * writer = new K3bCdrecordWriter( m_doc->burner(), this, this ); + // create cdrecord job + + writer->setSimulate( m_doc->dummy() ); + writer->setBurnSpeed( m_doc->speed() ); + writer->setDao( true ); + writer->setCueFile( m_cueFile ); + + m_writerJob = writer; + + } + + connect( m_writerJob, SIGNAL( infoMessage( const QString&, int ) ), this, SIGNAL( infoMessage( const QString&, int ) ) ); + connect( m_writerJob, SIGNAL( percent( int ) ), this, SLOT( slotWriterJobPercent( int ) ) ); + connect( m_writerJob, SIGNAL( processedSize( int, int ) ), this, SLOT( slotProcessedSize( int, int ) ) ); + connect( m_writerJob, SIGNAL( subPercent( int ) ), this, SIGNAL( subPercent( int ) ) ); + connect( m_writerJob, SIGNAL( processedSubSize( int, int ) ), this, SIGNAL( processedSubSize( int, int ) ) ); + connect( m_writerJob, SIGNAL( nextTrack( int, int ) ), this, SLOT( slotWriterNextTrack( int, int ) ) ); + connect( m_writerJob, SIGNAL( buffer( int ) ), this, SIGNAL( bufferStatus( int ) ) ); + connect( m_writerJob, SIGNAL( deviceBuffer( int ) ), this, SIGNAL( deviceBuffer( int ) ) ); + connect( m_writerJob, SIGNAL( writeSpeed( int, int ) ), this, SIGNAL( writeSpeed( int, int ) ) ); + connect( m_writerJob, SIGNAL( finished( bool ) ), this, SLOT( slotWriterJobFinished( bool ) ) ); + connect( m_writerJob, SIGNAL( newTask( const QString& ) ), this, SIGNAL( newTask( const QString& ) ) ); + connect( m_writerJob, SIGNAL( newSubTask( const QString& ) ), this, SIGNAL( newSubTask( const QString& ) ) ); + connect( m_writerJob, SIGNAL( debuggingOutput( const QString&, const QString& ) ), this, SIGNAL( debuggingOutput( const QString&, const QString& ) ) ); + + return true; +} + +void K3bVcdJob::slotWriterJobPercent( int p ) +{ + emit percent( ( int ) ( ( m_createimageonlypercent * ( m_currentcopy + 1 ) ) + p / ( m_doc->copies() + 2 ) ) ); +} + +void K3bVcdJob::slotProcessedSize( int cs, int ts ) +{ + emit processedSize( cs + ( ts * ( m_currentcopy - 1 ) ) , ts * m_doc->copies() ); +} + +void K3bVcdJob::slotWriterNextTrack( int t, int tt ) +{ + emit newSubTask( i18n( "Writing Track %1 of %2" ).arg( t ).arg( tt ) ); +} + +void K3bVcdJob::slotWriterJobFinished( bool success ) +{ + if ( m_canceled ) + return ; + + if ( m_currentcopy >= m_doc->copies() ) { + // remove bin-file if it is unfinished or the user selected to remove image + if ( QFile::exists( m_doc->vcdImage() ) ) { + if ( !m_doc->onTheFly() && m_doc->removeImages() || !m_imageFinished ) { + emit infoMessage( i18n( "Removing Binary file %1" ).arg( m_doc->vcdImage() ), K3bJob::SUCCESS ); + QFile::remove + ( m_doc->vcdImage() ); + m_doc->setVcdImage( "" ); + } + } + + // remove cue-file if it is unfinished or the user selected to remove image + if ( QFile::exists( m_cueFile ) ) { + if ( !m_doc->onTheFly() && m_doc->removeImages() || !m_imageFinished ) { + emit infoMessage( i18n( "Removing Cue file %1" ).arg( m_cueFile ), K3bJob::SUCCESS ); + QFile::remove + ( m_cueFile ); + m_cueFile = ""; + } + } + } + + if ( success ) { + // allright + // the writerJob should have emited the "simulation/writing successful" signal + if ( m_currentcopy >= m_doc->copies() ) { + jobFinished( true ); + } else { + m_currentcopy++; + startWriterjob(); + } + } else { + cancelAll(); + jobFinished( false ); + } +} + +void K3bVcdJob::parseInformation( const QString &text ) +{ + // parse warning + if ( text.contains( "mpeg user scan data: one or more BCD fields out of range for" ) ) { + int index = text.find( " for" ); + + emit infoMessage( i18n( "One or more BCD fields out of range for %1" ).arg( text.mid( index + 4 ).stripWhiteSpace() ), K3bJob::WARNING ); + + } else if ( text.contains( "mpeg user scan data: from now on, scan information data errors will not be reported anymore" ) ) { + emit infoMessage( i18n( "From now on, scan information data errors will not be reported anymore" ), K3bJob::INFO ); + emit infoMessage( i18n( "Consider enabling the 'update scan offsets' option, if it is not enabled already." ), K3bJob::INFO ); + + } else if ( text.contains( "APS' pts seems out of order (actual pts" ) ) { + int index = text.find( "(actual pts" ); + int index2 = text.find( ", last seen pts" ); + int index3 = text.find( ") -- ignoring this aps" ); + + emit infoMessage( i18n( "APS' pts seems out of order (actual pts %1, last seen pts %2)" ).arg( text.mid( index + 12, index2 - index - 12 ).stripWhiteSpace() ).arg( text.mid( index2 + 14, index3 - index2 - 14 ).stripWhiteSpace() ), K3bJob::WARNING ); + emit infoMessage( i18n( "Ignoring this aps" ), K3bJob::INFO ); + + } else if ( text.contains( "bad packet at packet" ) ) { + int index = text.find( "at packet #" ); + int index2 = text.find( "(stream byte offset" ); + int index3 = text.find( ") -- remaining " ); + int index4 = text.find( "bytes of stream will be ignored" ); + + emit infoMessage( i18n( "Bad packet at packet #%1 (stream byte offset %2)" ).arg( text.mid( index + 11, index2 - index - 11 ).stripWhiteSpace() ).arg( text.mid( index2 + 19, index3 - index2 - 19 ).stripWhiteSpace() ), K3bJob::WARNING ); + emit infoMessage( i18n( "Remaining %1 bytes of stream will be ignored." ).arg( text.mid( index3 + 15, index4 - index3 - 15 ).stripWhiteSpace() ), K3bJob::WARNING ); + } +} + +QString K3bVcdJob::jobDescription() const +{ + switch ( m_doc->vcdType() ) { + case K3bVcdDoc::VCD11: + return i18n( "Writing Video CD (Version 1.1)" ); + case K3bVcdDoc::VCD20: + return i18n( "Writing Video CD (Version 2.0)" ); + case K3bVcdDoc::SVCD10: + return i18n( "Writing Super Video CD" ); + case K3bVcdDoc::HQVCD: + return i18n( "Writing High-Quality Video CD" ); + default: + return i18n( "Writing Video CD" ); + } +} + + +QString K3bVcdJob::jobDetails() const +{ + return ( i18n( "1 MPEG (%1)", + "%n MPEGs (%1)", + m_doc->tracks() ->count() ).arg( KIO::convertSize( m_doc->size() ) ) + + ( m_doc->copies() > 1 + ? i18n( " - %n copy", " - %n copies", m_doc->copies() ) + : QString::null ) ); +} + +#include "k3bvcdjob.moc" diff --git a/libk3b/projects/videocd/k3bvcdjob.h b/libk3b/projects/videocd/k3bvcdjob.h new file mode 100644 index 0000000..917c8b1 --- /dev/null +++ b/libk3b/projects/videocd/k3bvcdjob.h @@ -0,0 +1,115 @@ +/* +* +* $Id: k3bvcdjob.h 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +#ifndef K3BVCDJOB_H +#define K3BVCDJOB_H + +#include + +class K3bVcdDoc; +class K3bVcdTrack; +class QString; +class K3bProcess; +class KProcess; +class QDataStream; +class K3bAbstractWriter; +class K3bDevice::Device; + + +class K3bVcdJob : public K3bBurnJob +{ + Q_OBJECT + + public: + K3bVcdJob( K3bVcdDoc*, K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + ~K3bVcdJob(); + + K3bDoc* doc() const; + K3bVcdDoc* vcdDoc() const + { + return m_doc; + } + K3bDevice::Device* writer() const; + + QString jobDescription() const; + QString jobDetails() const; + + public slots: + void start(); + void cancel(); + + private slots: + void cancelAll(); + + protected slots: + void slotVcdxBuildFinished(); + void slotParseVcdxBuildOutput( KProcess*, char* output, int len ); + + void slotWriterJobPercent( int p ); + void slotProcessedSize( int cs, int ts ); + void slotWriterNextTrack( int t, int tt ); + void slotWriterJobFinished( bool success ); + + + private: + bool prepareWriterJob(); + + void xmlGen(); + void vcdxBuild(); + void parseInformation( const QString& ); + void startWriterjob(); + + int m_copies; + int m_finishedCopies; + + unsigned long m_blocksToCopy; + unsigned long m_bytesFinishedTracks; + unsigned long m_bytesFinished; + + enum { stageUnknown, stageScan, stageWrite, _stage_max }; + + K3bVcdDoc* m_doc; + K3bDevice::Device* m_writer; + K3bDevice::Device* m_reader; + K3bVcdTrack* m_currentWrittenTrack; + + int m_speed; + int m_stage; + int m_currentcopy; + int m_currentWrittenTrackNumber; + + double m_createimageonlypercent; + + bool firstTrack; + bool m_burnProof; + bool m_keepImage; + bool m_onlyCreateImage; + bool m_onTheFly; + bool m_dummy; + bool m_fastToc; + bool m_readRaw; + bool m_imageFinished; + bool m_canceled; + + QString m_tempPath; + QString m_cueFile; + QString m_xmlFile; + QString m_collectedOutput; + + K3bAbstractWriter* m_writerJob; + K3bProcess* m_process; +}; + +#endif diff --git a/libk3b/projects/videocd/k3bvcdoptions.cpp b/libk3b/projects/videocd/k3bvcdoptions.cpp new file mode 100644 index 0000000..6009a4a --- /dev/null +++ b/libk3b/projects/videocd/k3bvcdoptions.cpp @@ -0,0 +1,146 @@ +/* +* +* $Id: k3bvcdoptions.cpp 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +// Kde Includes +#include +#include +#include +#include +#include + +// Qt Includes +#include +#include + +// K3b Includes +#include "k3bvcdoptions.h" +#include + +K3bVcdOptions::K3bVcdOptions() + : m_restriction( 0 ), + m_segment( 0 ), + m_sequence( 0 ), + m_pbcenabled( PbcEnabled() ), + m_pbcnumkeysenabled( PbcNumkeysEnabled() ), + m_volumeID( "VIDEOCD" ), + m_albumID( "" ), + m_volumeSetId( "" ), + m_publisher( QString( "K3b - Version %1" ).arg( k3bcore->version() ) ), + m_applicationId( "CDI/CDI_VCD.APP;1" ), + m_systemId( "CD-RTOS CD-BRIDGE" ), + m_vcdclass( "vcd" ), + m_vcdversion( "2.0" ), + m_pregapleadout( 150 ), + m_pregaptrack( 150 ), + m_frontmargintrack( 30 ), + m_rearmargintrack( 45 ), + m_frontmargintrackSVCD( 0 ), + m_rearmargintrackSVCD( 0 ), + m_mpegversion( 1 ), + m_volumeCount( 1 ), + m_volumeNumber( 1 ), + m_autodetect( true ), + m_cdisupport( false ), + m_brokensvcdmode( false ), + m_VCD30interpretation( false ), + m_sector2336( false ), + m_updatescanoffsets( false ), + m_relaxedaps( false ), + m_segmentfolder( true ), + m_usegaps( false ) +{} + +bool K3bVcdOptions::checkCdiFiles() +{ + m_cdisize = 0; + if ( !QFile::exists( locate( "data", "k3b/cdi/cdi_imag.rtf" ) ) ) + return false; + if ( !QFile::exists( locate( "data", "k3b/cdi/cdi_text.fnt" ) ) ) + return false; + if ( !QFile::exists( locate( "data", "k3b/cdi/cdi_vcd.app" ) ) ) + return false; + if ( !QFile::exists( locate( "data", "k3b/cdi/cdi_vcd.cfg" ) ) ) + return false; + + m_cdisize += QFile( locate( "data", "k3b/cdi/cdi_imag.rtf" ) ).size(); + m_cdisize += QFile( locate( "data", "k3b/cdi/cdi_text.fnt" ) ).size(); + m_cdisize += QFile( locate( "data", "k3b/cdi/cdi_vcd.app" ) ).size(); + m_cdisize += QFile( locate( "data", "k3b/cdi/cdi_vcd.cfg" ) ).size(); + + return true; +} + +void K3bVcdOptions::save( KConfigBase* c ) +{ + c->writeEntry( "volume_id", m_volumeID ); + c->writeEntry( "album_id", m_albumID ); + c->writeEntry( "volume_set_id", m_volumeSetId ); + c->writeEntry( "preparer", m_preparer ); + c->writeEntry( "publisher", m_publisher ); + c->writeEntry( "volume_count", m_volumeCount ); + c->writeEntry( "volume_number", m_volumeNumber ); + c->writeEntry( "autodetect", m_autodetect ); + c->writeEntry( "cdi_support", m_cdisupport ); + c->writeEntry( "broken_svcd_mode", m_brokensvcdmode ); + c->writeEntry( "VCD30interpretation", m_VCD30interpretation ); + c->writeEntry( "2336_sectors", m_sector2336 ); + c->writeEntry( "UpdateScanOffsets", m_updatescanoffsets ); + c->writeEntry( "RelaxedAps", m_relaxedaps ); + c->writeEntry( "PbcEnabled", m_pbcenabled ); + c->writeEntry( "SegmentFolder", m_segmentfolder ); + c->writeEntry( "Restriction", m_restriction ); + c->writeEntry( "PreGapLeadout", m_pregapleadout ); + c->writeEntry( "PreGapTrack", m_pregaptrack ); + c->writeEntry( "FrontMarginTrack", m_frontmargintrack ); + c->writeEntry( "RearMarginTrack", m_rearmargintrack ); + c->writeEntry( "UseGaps", m_usegaps ); +} + + +K3bVcdOptions K3bVcdOptions::load( KConfigBase* c ) +{ + K3bVcdOptions options; + + options.setVolumeId( c->readEntry( "volume_id", options.volumeId() ) ); + options.setAlbumId( c->readEntry( "album_id", options.albumId() ) ); + options.setVolumeSetId( c->readEntry( "volume_set_id", options.volumeSetId() ) ); + options.setPreparer( c->readEntry( "preparer", options.preparer() ) ); + options.setPublisher( c->readEntry( "publisher", options.publisher() ) ); + options.setVolumeCount( c->readNumEntry( "volume_count", options.volumeCount() ) ); + options.setVolumeNumber( c->readNumEntry( "volume_number", options.volumeNumber() ) ); + options.setAutoDetect( c->readBoolEntry( "autodetect", options.AutoDetect() ) ); + options.setCdiSupport( c->readBoolEntry( "cdi_support", options.CdiSupport() ) ); + options.setNonCompliantMode( c->readBoolEntry( "broken_svcd_mode", options.NonCompliantMode() ) ); + options.setVCD30interpretation( c->readBoolEntry( "VCD30interpretation", options.VCD30interpretation() ) ); + options.setSector2336( c->readBoolEntry( "2336_sectors", options.Sector2336() ) ); + options.setUpdateScanOffsets( c->readBoolEntry( "UpdateScanOffsets", options.UpdateScanOffsets() ) ); + options.setRelaxedAps( c->readBoolEntry( "RelaxedAps", options.RelaxedAps() ) ); + options.setPbcEnabled( c->readBoolEntry( "PbcEnabled", options.PbcEnabled() ) ); + options.setSegmentFolder( c->readBoolEntry( "SegmentFolder", options.SegmentFolder() ) ); + options.setRestriction( c->readNumEntry( "Restriction", options.Restriction() ) ); + options.setPreGapLeadout( c->readNumEntry( "PreGapLeadout", options.PreGapLeadout() ) ); + options.setPreGapTrack( c->readNumEntry( "PreGapTrack", options.PreGapTrack() ) ); + options.setFrontMarginTrack( c->readNumEntry( "FrontMarginTrack", options.FrontMarginTrack() ) ); + options.setRearMarginTrack( c->readNumEntry( "RearMarginTrack", options.RearMarginTrack() ) ); + options.setUseGaps( c->readBoolEntry( "UseGaps", options.UseGaps() ) ); + + return options; +} + +K3bVcdOptions K3bVcdOptions::defaults() +{ + // let the constructor create defaults + return K3bVcdOptions(); +} diff --git a/libk3b/projects/videocd/k3bvcdoptions.h b/libk3b/projects/videocd/k3bvcdoptions.h new file mode 100644 index 0000000..aa5fed2 --- /dev/null +++ b/libk3b/projects/videocd/k3bvcdoptions.h @@ -0,0 +1,377 @@ +/* +* +* $Id: k3bvcdoptions.h 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +#ifndef K3B_VCD_OPTIONS_H +#define K3B_VCD_OPTIONS_H + +#include +#include "k3b_export.h" + +class KConfigBase; + +class LIBK3B_EXPORT K3bVcdOptions +{ + public: + K3bVcdOptions(); + const QString& volumeId() const + { + return m_volumeID; + } + const QString& albumId() const + { + return m_albumID; + } + const QString& volumeSetId() const + { + return m_volumeSetId; + } + const QString& preparer() const + { + return m_preparer; + } + const QString& publisher() const + { + return m_publisher; + } + + const QString& applicationId() const + { + return m_applicationId; + } + const QString& systemId() const + { + return m_systemId; + } + + const QString& vcdClass() const + { + return m_vcdclass; + } + const QString& vcdVersion() const + { + return m_vcdversion; + } + + const int PreGapLeadout() + { + return m_pregapleadout; + } + const int PreGapTrack() + { + return m_pregaptrack; + } + const int FrontMarginTrack() + { + return m_frontmargintrack; + } + const int RearMarginTrack() + { + return m_rearmargintrack; + } + const int FrontMarginTrackSVCD() + { + return m_frontmargintrackSVCD; + } + const int RearMarginTrackSVCD() + { + return m_rearmargintrackSVCD; + } + + const int mpegVersion() const + { + return m_mpegversion; + } + + const int volumeCount() const + { + return m_volumeCount; + } + const int volumeNumber() const + { + return m_volumeNumber; + } + + const bool AutoDetect() const + { + return m_autodetect; + } + const bool CdiSupport() const + { + return m_cdisupport; + } + const bool NonCompliantMode() const + { + return m_brokensvcdmode; + } + const bool VCD30interpretation() const + { + return m_VCD30interpretation; + } + const bool Sector2336() const + { + return m_sector2336; + } + const bool UpdateScanOffsets() const + { + return m_updatescanoffsets; + } + const bool RelaxedAps() const + { + return m_relaxedaps; + } + const bool UseGaps() const + { + return m_usegaps; + } + const unsigned long long CDIsize() const + { + return m_cdisize; + } + + void setAlbumId( const QString& s ) + { + m_albumID = s; + } + void setVolumeId( const QString& s ) + { + m_volumeID = s; + } + void setVolumeSetId( const QString& s ) + { + m_volumeSetId = s; + } + void setPreparer( const QString& s ) + { + m_preparer = s; + } + void setPublisher( const QString& s ) + { + m_publisher = s; + } + + void setVcdClass( const QString& s ) + { + m_vcdclass = s; + } + void setVcdVersion( const QString& s ) + { + m_vcdversion = s; + } + + void setPreGapLeadout( const int i ) + { + m_pregapleadout = i; + } + void setPreGapTrack( const int i ) + { + m_pregaptrack = i; + } + void setFrontMarginTrack( const int i ) + { + m_frontmargintrack = i; + } + void setRearMarginTrack( const int i ) + { + m_rearmargintrack = i; + } + void setFrontMarginTrackSVCD( const int i ) + { + m_frontmargintrackSVCD = i; + } + void setRearMarginTrackSVCD( const int i ) + { + m_rearmargintrackSVCD = i; + } + + void setMpegVersion( const int v ) + { + m_mpegversion = v; + } + void setVolumeCount( const int c ) + { + m_volumeCount = c; + } + void setVolumeNumber( const int n ) + { + m_volumeNumber = n; + } + + void setAutoDetect( const bool& b ) + { + m_autodetect = b; + } + void setCdiSupport( const bool& b ) + { + m_cdisupport = b; + } + void setNonCompliantMode( const bool& b ) + { + m_brokensvcdmode = b; + } + void setVCD30interpretation( const bool& b ) + { + m_VCD30interpretation = b; + } + void setSector2336( const bool& b ) + { + m_sector2336 = b; + } + void setUpdateScanOffsets( const bool& b ) + { + m_updatescanoffsets = b; + } + void setRelaxedAps( const bool& b ) + { + m_relaxedaps = b; + } + void setUseGaps( const bool& b ) + { + m_usegaps = b; + } + + bool checkCdiFiles(); + void save( KConfigBase* c ); + + static K3bVcdOptions load( KConfigBase* c ); + static K3bVcdOptions defaults(); + + void setPbcEnabled( const bool& b ) + { + m_pbcenabled = b; + } + bool PbcEnabled() const + { + return m_pbcenabled; + }; + void setPbcNumkeysEnabled( const bool& b ) + { + m_pbcnumkeysenabled = b; + } + bool PbcNumkeysEnabled() const + { + return m_pbcnumkeysenabled; + }; + + void setPbcPlayTime( const int i ) + { + m_def_pbcplaytime = i; + } + int PbcPlayTime( ) + { + return m_def_pbcplaytime; + } + + void setPbcWaitTime( const int i ) + { + m_def_pbcwaittime = i; + } + int PbcWaitTime( ) + { + return m_def_pbcwaittime; + } + + void setSegmentFolder( const bool& b ) + { + m_segmentfolder = b; + } + bool SegmentFolder() const + { + return m_segmentfolder; + }; + + void setRestriction( const int i ) + { + m_restriction = i; + } + int Restriction() const + { + return m_restriction; + }; + void increaseSegments( ) + { + m_segment += 1; + } + void decreaseSegments( ) + { + m_segment -= 1; + } + bool haveSegments() const + { + return m_segment > 0; + }; + void increaseSequence( ) + { + m_sequence += 1; + } + void decreaseSequence( ) + { + m_sequence -= 1; + } + + bool haveSequence() const + { + return m_sequence > 0; + }; + + private: + int m_restriction; + int m_segment; + int m_sequence; + + // pbc + bool m_pbcenabled; + bool m_pbcnumkeysenabled; + + // volume descriptor + QString m_volumeID; + QString m_albumID; + QString m_volumeSetId; + + QString m_preparer; + QString m_publisher; + + QString m_applicationId; + QString m_systemId; + + QString m_vcdclass; + QString m_vcdversion; + + int m_pregapleadout; + int m_pregaptrack; + int m_frontmargintrack; + int m_rearmargintrack; + int m_frontmargintrackSVCD; + int m_rearmargintrackSVCD; + + int m_mpegversion; + int m_volumeCount; + int m_volumeNumber; + + bool m_autodetect; + bool m_cdisupport; + bool m_brokensvcdmode; + bool m_VCD30interpretation; + bool m_sector2336; + bool m_updatescanoffsets; + bool m_relaxedaps; + bool m_segmentfolder; + bool m_usegaps; + + int m_def_pbcplaytime; + int m_def_pbcwaittime; + unsigned long long m_cdisize; +}; + +#endif diff --git a/libk3b/projects/videocd/k3bvcdtrack.cpp b/libk3b/projects/videocd/k3bvcdtrack.cpp new file mode 100644 index 0000000..7f0043f --- /dev/null +++ b/libk3b/projects/videocd/k3bvcdtrack.cpp @@ -0,0 +1,456 @@ +/* +* +* $Id: k3bvcdtrack.cpp 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +// K3b Includes +#include "k3bvcdtrack.h" +#include + +K3bVcdTrack::K3bVcdTrack( QPtrList* parent, const QString& filename ) + : m_pbcnumkeys( true ), + m_pbcnumkeysuserdefined( false ), + m_file( filename ) +{ + m_parent = parent; + m_title = QFileInfo( m_file ).baseName( true ); + + m_revreflist = new QPtrList; + + for ( int i = 0; i < K3bVcdTrack::_maxPbcTracks; i++ ) { + m_pbctrackmap.insert( i, 0L ); + m_pbcnontrackmap.insert( i, K3bVcdTrack::DISABLED ); + m_pbcusrdefmap.insert( i, false ); + } + + m_reactivity = false; + + m_definedkeysmap.clear(); + + mpeg_info = new Mpeginfo(); +} + + +K3bVcdTrack::~K3bVcdTrack() +{} + + +KIO::filesize_t K3bVcdTrack::size() const +{ + return m_file.size(); +} + +int K3bVcdTrack::index() const +{ + int i = m_parent->find( this ); + if ( i < 0 ) + kdDebug() << "(K3bVcdTrack) I'm not part of my parent!" << endl; + return i; +} + +void K3bVcdTrack::addToRevRefList( K3bVcdTrack* revreftrack ) +{ + kdDebug() << "K3bVcdTrack::addToRevRefList: track = " << revreftrack << endl; + + m_revreflist->append( revreftrack ); + + kdDebug() << "K3bVcdTrack::hasRevRef count = " << m_revreflist->count() << " empty = " << m_revreflist->isEmpty() << endl; +} + +void K3bVcdTrack::delFromRevRefList( K3bVcdTrack* revreftrack ) +{ + if ( !m_revreflist->isEmpty() ) { + m_revreflist->remove + ( revreftrack ); + } +} + +bool K3bVcdTrack::hasRevRef() +{ + return !m_revreflist->isEmpty() ; +} + +void K3bVcdTrack::delRefToUs() +{ + for ( K3bVcdTrack * track = m_revreflist->first(); track; track = m_revreflist->next() ) { + for ( int i = 0; i < K3bVcdTrack::_maxPbcTracks; i++ ) { + kdDebug() << "K3bVcdTrack::delRefToUs count = " << m_revreflist->count() << " empty = " << m_revreflist->isEmpty() << " track = " << track << " this = " << this << endl; + if ( this == track->getPbcTrack( i ) ) { + track->setPbcTrack( i ); + track->setUserDefined( i, false ); + track->delFromRevRefList( this ); + } + } + } +} + +void K3bVcdTrack::delRefFromUs() +{ + for ( int i = 0; i < K3bVcdTrack::_maxPbcTracks; i++ ) { + if ( this->getPbcTrack( i ) ) { + this->getPbcTrack( i ) ->delFromRevRefList( this ); + } + } +} + +void K3bVcdTrack::setPbcTrack( int which, K3bVcdTrack* pbctrack ) +{ + kdDebug() << "K3bVcdTrack::setPbcTrack " << which << ", " << pbctrack << endl; + m_pbctrackmap.replace( which, pbctrack ); +} + +void K3bVcdTrack::setPbcNonTrack( int which, int type ) +{ + kdDebug() << "K3bVcdTrack::setNonPbcTrack " << which << ", " << type << endl; + m_pbcnontrackmap.replace( which, type ); +} + +void K3bVcdTrack::setUserDefined( int which, bool ud ) +{ + m_pbcusrdefmap.replace( which, ud ); +} + +K3bVcdTrack* K3bVcdTrack::getPbcTrack( const int& which ) +{ + if ( m_pbctrackmap.find( which ) == m_pbctrackmap.end() ) + return 0; + else + return m_pbctrackmap[ which ]; +} + +int K3bVcdTrack::getNonPbcTrack( const int& which ) +{ + if ( m_pbcnontrackmap.find( which ) == m_pbcnontrackmap.end() ) + return 0; + else + return m_pbcnontrackmap[ which ]; +} + +bool K3bVcdTrack::isPbcUserDefined( int which ) +{ + return m_pbcusrdefmap[ which ]; +} + +const QString K3bVcdTrack::resolution() +{ + if ( mpeg_info->has_video ) { + for ( int i = 0; i < 2; i++ ) { + if ( mpeg_info->video[ i ].seen ) { + return QString( "%1 x %2" ).arg( mpeg_info->video[ i ].hsize ).arg( mpeg_info->video[ i ].vsize ); + } + } + } + + return i18n( "n/a" ); +} + +const QString K3bVcdTrack::highresolution() +{ + if ( mpeg_info->has_video ) { + if ( mpeg_info->video[ 2 ].seen ) { + return QString( "%1 x %2" ).arg( mpeg_info->video[ 2 ].hsize ).arg( mpeg_info->video[ 2 ].vsize ); + } + } + return i18n( "n/a" ); +} + +const QString K3bVcdTrack::video_frate() +{ + if ( mpeg_info->has_video ) { + for ( int i = 0; i < 2; i++ ) { + if ( mpeg_info->video[ i ].seen ) { + return QString::number( mpeg_info->video[ i ].frate ); + } + } + } + + return i18n( "n/a" ); +} + +const QString K3bVcdTrack::video_bitrate() +{ + if ( mpeg_info->has_video ) { + for ( int i = 0; i < 2; i++ ) { + if ( mpeg_info->video[ i ].seen ) { + return i18n( "%1 bit/s" ).arg( mpeg_info->video[ i ].bitrate ) ; + } + } + } + + return i18n( "n/a" ); +} + + + +const QString K3bVcdTrack::video_format() +{ + if ( mpeg_info->has_video ) { + for ( int i = 0; i < 2; i++ ) { + if ( mpeg_info->video[ i ].seen ) { + switch ( mpeg_info->video[ i ].video_format ) { + case 0 : + return i18n( "Component" ); + break; + case 1 : + return "PAL"; + break; + case 2 : + return "NTSC"; + break; + case 3 : + return "SECAM"; + break; + case 4 : + return "MAC"; + break; + case 5 : + default: + return i18n( "Unspecified" ); + kdDebug() << "K3bVcdTrack::video_format() :" << mpeg_info->video[ i ].video_format << endl; + break; + } + } + } + } + return i18n( "n/a" ); +} + +const QString K3bVcdTrack::video_chroma() +{ + if ( mpeg_info->has_video ) { + // MPEG1 only supports 4:2:0 Format + if ( version() == K3bMpegInfo::MPEG_VERS_MPEG1 ) + return QString( "4:2:0" ); + + for ( int i = 0; i < 2; i++ ) { + if ( mpeg_info->video[ i ].seen ) { + switch ( mpeg_info->video[ i ].chroma_format ) { + case 1 : + return QString( "4:2:0" ); + break; + case 2 : + return QString( "4:2:2" ); + break; + case 3 : + return QString( "4:4:4" ); + break; + + } + } + } + } + + return i18n( "n/a" ); +} + +const QString K3bVcdTrack::audio_layer() +{ + if ( mpeg_info->has_audio ) { + for ( int i = 0; i < 2; i++ ) { + if ( mpeg_info->audio[ i ].seen ) { + return QString::number( mpeg_info->audio[ i ].layer ); + } + } + } + + return i18n( "n/a" ); +} + +const QString K3bVcdTrack::audio_bitrate() +{ + if ( mpeg_info->has_audio ) { + for ( int i = 0; i < 2; i++ ) { + if ( mpeg_info->audio[ i ].seen ) { + return i18n( "%1 bit/s" ).arg( mpeg_info->audio[ i ].bitrate ) ; + } + } + } + + return i18n( "n/a" ); +} + +const QString K3bVcdTrack::audio_sampfreq() +{ + if ( mpeg_info->has_audio ) { + for ( int i = 0; i < 2; i++ ) { + if ( mpeg_info->audio[ i ].seen ) { + return i18n( "%1 Hz" ).arg( mpeg_info->audio[ i ].sampfreq ) ; + } + } + } + + return i18n( "n/a" ); +} + +const QString K3bVcdTrack::audio_mode( ) +{ + if ( mpeg_info->has_audio ) { + for ( int i = 2; i >= 0; i-- ) + if ( mpeg_info->audio[ i ].seen ) + return QString( audio_type2str( mpeg_info->audio[ i ].version, mpeg_info->audio[ i ].mode, i ) ); + + } + + return i18n( "n/a" ); +} + +const QString K3bVcdTrack::audio_copyright( ) +{ + if ( mpeg_info->has_audio ) { + for ( int i = 2; i >= 0; i-- ) + if ( mpeg_info->audio[ i ].seen ) + if ( mpeg_info->audio[ i ].copyright ) + return QString( "(c) " ) + ( mpeg_info->audio[ i ].original ? i18n( "original" ) : i18n( "duplicate" ) ); + else + return ( mpeg_info->audio[ i ].original ? i18n( "original" ) : i18n( "duplicate" ) ); + } + + return i18n( "n/a" ); +} + +const QString K3bVcdTrack::mpegTypeS( bool audio ) +{ + if ( mpeg_info->has_video && !audio ) { + for ( int i = 0; i < 3; i++ ) + if ( mpeg_info->video[ i ].seen ) { + if ( i == 0 ) { + return QString( "MPEG%1 " ).arg( mpeg_info->version ) + i18n( "Motion Picture" ); + } else { + return QString( "MPEG%1 " ).arg( mpeg_info->version ) + i18n( "Still Picture" ); + } + } + } + if ( mpeg_info->has_audio && audio ) { + for ( int i = 0; i < 3; i++ ) + if ( mpeg_info->audio[ i ].seen ) { + return QString( "MPEG%1 " ).arg( mpeg_info->audio[ i ].version ) + i18n( "Layer %1" ).arg( mpeg_info->audio[ i ].layer ); + } + } + + return i18n( "n/a" ); +} + +const int K3bVcdTrack::mpegType( ) +{ + if ( mpeg_info->has_video ) { + for ( int i = 0; i < 3; i++ ) + if ( mpeg_info->video[ i ].seen ) { + if ( i == 0 ) { + return 0; // MPEG_MOTION; + } else { + return 1; // MPEG_STILL; + } + } + } + if ( mpeg_info->has_audio ) { + for ( int i = 0; i < 3; i++ ) + if ( mpeg_info->audio[ i ].seen ) + return 2; // MPEG_AUDIO; + } + + return -1; // MPEG_UNKNOWN; +} + +const QString K3bVcdTrack::audio_type2str( unsigned int version, unsigned int audio_mode, unsigned int audio_type ) +{ + kdDebug() << "K3bVcdTrack::audio_type2str() version:" << version << " audio_mode:" << audio_mode << " audio_type:" << audio_type << endl; + + QString audio_types[ 3 ][ 5 ] = { + { + i18n( "unknown" ), + i18n( "invalid" ), + QString::null, + QString::null, + QString::null + }, + { + i18n( "stereo" ), + i18n( "joint stereo" ), + i18n( "dual channel" ), + i18n( "single channel" ) + }, + { + QString::null, + i18n( "dual channel" ), + i18n( "surround sound" ), + QString::null, + QString::null + } + }; + switch ( version ) { + case K3bMpegInfo::MPEG_VERS_MPEG1: + return audio_types[ 1 ][ audio_mode ]; + break; + + case K3bMpegInfo::MPEG_VERS_MPEG2: + if ( audio_type > 0 ) { + return audio_types[ 2 ][ audio_type ]; + } + return audio_types[ 1 ][ audio_mode ]; + break; + } + + return i18n( "n/a" ); +} + +// convert a time in second to HH:mm:ss notation +QString K3bVcdTrack::SecsToHMS( double duration ) +{ + byte hours = ( byte ) ( duration / 3600 ); + byte mins = ( byte ) ( ( duration / 60 ) - ( hours * 60 ) ); + float secs = duration - 60 * mins - 3600 * hours; + if ( hours != 0 ) { + return QString( "%1:" ).arg( hours ).rightJustify( 3, ' ' ) + QString( "%1:" ).arg( mins ).rightJustify( 3, '0' ) + QString::number( secs, 'f', 2 ); + } + if ( mins != 0 ) { + return QString( "%1:" ).arg( mins ).rightJustify( 3, '0' ) + QString::number( secs, 'f', 2 ); + } + return QString::number( secs, 'f', 2 ); +} + +void K3bVcdTrack::PrintInfo() +{ + + kdDebug() << "K3bVcdTrack::PrintInfo() ....................." << endl; + kdDebug() << " version : MPEG" << version() << endl; + kdDebug() << " duration : " << duration() << endl; + kdDebug() << " muxrate : " << muxrate() << endl; + kdDebug() << " video ......................................" << endl; + kdDebug() << " type : " << mpegTypeS() << endl; + kdDebug() << " resolution : " << resolution() << endl; + kdDebug() << " high resolution: " << highresolution() << endl; + kdDebug() << " frate : " << video_frate() << endl; + kdDebug() << " bitrate : " << video_bitrate() << endl; + kdDebug() << " format : " << video_format( ) << endl; + kdDebug() << " chroma : " << video_chroma( ) << endl; + kdDebug() << " audio ......................................" << endl; + kdDebug() << " type : " << mpegTypeS( true ) << endl; + kdDebug() << " mode : " << audio_mode() << endl; + kdDebug() << " layer : " << audio_layer() << endl; + kdDebug() << " bitrate : " << audio_bitrate() << endl; + kdDebug() << " sampfreq : " << audio_sampfreq() << endl; + +} diff --git a/libk3b/projects/videocd/k3bvcdtrack.h b/libk3b/projects/videocd/k3bvcdtrack.h new file mode 100644 index 0000000..0d9a3cf --- /dev/null +++ b/libk3b/projects/videocd/k3bvcdtrack.h @@ -0,0 +1,198 @@ +/* +* +* $Id: k3bvcdtrack.h 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +#ifndef K3BVCDTRACK_H +#define K3BVCDTRACK_H + +// Qt Includes +#include +#include +#include +#include + +// Kde Includes +#include + +// K3b Includes +#include "mpeginfo/k3bmpeginfo.h" +#include "k3b_export.h" +class LIBK3B_EXPORT K3bVcdTrack +{ + public: + K3bVcdTrack( QPtrList* parent, const QString& filename ); + ~K3bVcdTrack(); + + QString fileName() const + { + return QFileInfo( m_file ).fileName(); + } + QString absPath() const + { + return QFileInfo( m_file ).absFilePath(); + } + KIO::filesize_t size() const; + int index() const; + + const QString& title() const + { + return m_title; + } + void setTitle( const QString& t ) + { + m_title = t; + } + bool isSegment() + { + return mpegType() == 1; + }; + + + + // PBC + enum PbcTracks { PREVIOUS, NEXT, RETURN, DEFAULT, AFTERTIMEOUT, _maxPbcTracks }; + enum PbcTypes { DISABLED, VIDEOEND }; + + void addToRevRefList( K3bVcdTrack* revreftrack ); + void delFromRevRefList( K3bVcdTrack* revreftrack ); + bool hasRevRef(); + void delRefToUs(); + void delRefFromUs(); + + void setPbcTrack( int, K3bVcdTrack* pbctrack = 0L ); + void setPbcNonTrack( int, int ); + void setUserDefined( int, bool ); + void setPlayTime( int t ) + { + m_pbcplaytime = t; + } + void setWaitTime( int t ) + { + m_pbcwaittime = t; + } + void setReactivity( bool b ) + { + m_reactivity = b; + } + void setPbcNumKeys( const bool& b ) + { + m_pbcnumkeys = b; + } + bool PbcNumKeys() const + { + return m_pbcnumkeys; + }; + void setPbcNumKeysUserdefined( const bool& b ) + { + m_pbcnumkeysuserdefined = b; + }; + bool PbcNumKeysUserdefined() const + { + return m_pbcnumkeysuserdefined; + }; + + K3bVcdTrack* getPbcTrack( const int& ); + int getNonPbcTrack( const int& ); + bool isPbcUserDefined( int ); + int getPlayTime() + { + return m_pbcplaytime; + } + int getWaitTime() + { + return m_pbcwaittime; + } + bool Reactivity() + { + return m_reactivity; + } + + // Numeric keys + void setDefinedNumKey( int key, K3bVcdTrack* track ) + { + m_definedkeysmap.insert( key, track ); + } + void delDefinedNumKey( int key ) + { + m_definedkeysmap.remove( key ); + } + void delDefinedNumKey() + { + m_definedkeysmap.clear(); + } + QMap DefinedNumKey() + { + return m_definedkeysmap; + } + + // Mpeg Infos + const QString resolution(); + const QString highresolution(); + const QString video_frate(); + const QString video_bitrate(); + const QString audio_layer(); + const QString audio_bitrate(); + const QString audio_sampfreq(); + + const QString duration() + { + return SecsToHMS( mpeg_info->playing_time ); + }; + const int version() + { + return mpeg_info->version; + }; + const unsigned long muxrate() + { + return mpeg_info->muxrate; + }; + const QString video_format( ); + const QString video_chroma( ); + const QString audio_mode( ); + const QString audio_copyright( ); + const QString mpegTypeS( bool audio = false ); + const int mpegType(); + + void PrintInfo(); + + Mpeginfo* mpeg_info; + + protected: + + const QString audio_type2str( unsigned int , unsigned int, unsigned int ); + QString SecsToHMS( double ); + + QPtrList* m_parent; + + // PBC + QPtrList* m_revreflist; // List of Tracks which points to us + QMap m_pbctrackmap; // Pbc Tracks (Previous, Next, ...) + QMap m_pbcnontrackmap; // Pbc NON Track types (Previous, Next, ...) + QMap m_pbcusrdefmap; // Pbc is userdefined or defaults (Previous, Next, ...) + QMap m_definedkeysmap; + + bool m_pbcnumkeys; + bool m_pbcnumkeysuserdefined; + + int m_pbcplaytime; + int m_pbcwaittime; + /********************************************************************************/ + + bool m_reactivity; + int m_filetype; + QFile m_file; + QString m_title; +}; + +#endif diff --git a/libk3b/projects/videocd/k3bvcdxmlview.cpp b/libk3b/projects/videocd/k3bvcdxmlview.cpp new file mode 100644 index 0000000..0b6f250 --- /dev/null +++ b/libk3b/projects/videocd/k3bvcdxmlview.cpp @@ -0,0 +1,440 @@ +/* +* +* $Id: k3bvcdxmlview.cpp 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* THX to Manfred Odenstein +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +#include + +#include +#include + + +#include "k3bvcdxmlview.h" +#include "k3bvcdtrack.h" +#include +#include + +K3bVcdXmlView::K3bVcdXmlView( K3bVcdDoc* pDoc ) +{ + + m_doc = pDoc; + +} + +K3bVcdXmlView::~K3bVcdXmlView() +{} + +bool K3bVcdXmlView::write( const QString& fname ) +{ + + QDomDocument xmlDoc( "videocd PUBLIC \"-//GNU//DTD VideoCD//EN\" \"http://www.gnu.org/software/vcdimager/videocd.dtd\"" ); + // xmlDoc.appendChild( xmlDoc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"iso-8859-1\"" ) ); + xmlDoc.appendChild( xmlDoc.createProcessingInstruction( "xml", "version=\"1.0\"" ) ); + + // create root element + QDomElement root = xmlDoc.createElement( "videocd" ); + root.setAttribute( "xmlns", "http://www.gnu.org/software/vcdimager/1.0/" ); + root.setAttribute( "class", m_doc->vcdOptions() ->vcdClass() ); + root.setAttribute( "version", m_doc->vcdOptions() ->vcdVersion() ); + xmlDoc.appendChild( root ); + + // create option elements + + // Broken SVCD mode - NonCompliantMode + if ( m_doc->vcdOptions() ->NonCompliantMode() ) { + QDomElement elemOption; + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "svcd vcd30 mpegav" ); + elemOption.setAttribute( "value", "true" ); + + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "svcd vcd30 entrysvd" ); + elemOption.setAttribute( "value", "true" ); + } + + // VCD3.0 track interpretation + if ( m_doc->vcdOptions() ->VCD30interpretation() ) { + QDomElement elemOption; + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "svcd vcd30 tracksvd" ); + elemOption.setAttribute( "value", "true" ); + } + + // Relaxed aps + if ( m_doc->vcdOptions() ->RelaxedAps() ) { + QDomElement elemOption; + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "relaxed aps" ); + elemOption.setAttribute( "value", "true" ); + } + + // Update scan offsets + if ( m_doc->vcdOptions() ->UpdateScanOffsets() ) { + QDomElement elemOption; + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "update scan offsets" ); + elemOption.setAttribute( "value", "true" ); + + } + + // Gaps & Margins + if ( m_doc->vcdOptions() ->UseGaps() ) { + QDomElement elemOption; + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "leadout pregap" ); + elemOption.setAttribute( "value", m_doc->vcdOptions() ->PreGapLeadout() ); + + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "track pregap" ); + elemOption.setAttribute( "value", m_doc->vcdOptions() ->PreGapTrack() ); + + if ( m_doc->vcdOptions() ->vcdClass() == "vcd" ) { + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "track front margin" ); + elemOption.setAttribute( "value", m_doc->vcdOptions() ->FrontMarginTrack() ); + + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "track rear margin" ); + elemOption.setAttribute( "value", m_doc->vcdOptions() ->RearMarginTrack() ); + } else { + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "track front margin" ); + elemOption.setAttribute( "value", m_doc->vcdOptions() ->FrontMarginTrackSVCD() ); + + elemOption = addSubElement( xmlDoc, root, "option" ); + elemOption.setAttribute( "name", "track rear margin" ); + elemOption.setAttribute( "value", m_doc->vcdOptions() ->RearMarginTrackSVCD() ); + } + + } + + // create info element + QDomElement elemInfo = addSubElement( xmlDoc, root, "info" ); + addSubElement( xmlDoc, elemInfo, "album-id", m_doc->vcdOptions() ->albumId().upper() ); + addSubElement( xmlDoc, elemInfo, "volume-count", m_doc->vcdOptions() ->volumeCount() ); + addSubElement( xmlDoc, elemInfo, "volume-number", m_doc->vcdOptions() ->volumeNumber() ); + addSubElement( xmlDoc, elemInfo, "restriction", m_doc->vcdOptions() ->Restriction() ); + + // create pvd element + QDomElement elemPvd = addSubElement( xmlDoc, root, "pvd" ); + addSubElement( xmlDoc, elemPvd, "volume-id", m_doc->vcdOptions() ->volumeId().upper() ); + addSubElement( xmlDoc, elemPvd, "system-id", m_doc->vcdOptions() ->systemId() ); + addSubElement( xmlDoc, elemPvd, "application-id", m_doc->vcdOptions() ->applicationId() ); + addSubElement( xmlDoc, elemPvd, "preparer-id", QString( "K3b - Version %1" ).arg( k3bcore->version() ).upper() ); + addSubElement( xmlDoc, elemPvd, "publisher-id", m_doc->vcdOptions() ->publisher().upper() ); + + + // create filesystem element + QDomElement elemFileSystem = addSubElement( xmlDoc, root, "filesystem" ); + + // SEGMENT folder, some standalone DVD-Player need this + if ( !m_doc->vcdOptions() ->haveSegments() && m_doc->vcdOptions() ->SegmentFolder() ) + addFolderElement( xmlDoc, elemFileSystem, "SEGMENT" ); + + // create cdi element + if ( m_doc->vcdOptions() ->CdiSupport() ) { + QDomElement elemFolder = addFolderElement( xmlDoc, elemFileSystem, "CDI" ); + + addFileElement( xmlDoc, elemFolder, locate( "data", "k3b/cdi/cdi_imag.rtf" ), "CDI_IMAG.RTF", true ); + addFileElement( xmlDoc, elemFolder, locate( "data", "k3b/cdi/cdi_text.fnt" ), "CDI_TEXT.FNT" ); + addFileElement( xmlDoc, elemFolder, locate( "data", "k3b/cdi/cdi_vcd.app" ), "CDI_VCD.APP" ); + + QString usercdicfg = locateLocal( "appdata", "cdi/cdi_vcd.cfg" ); + if ( QFile::exists( usercdicfg ) ) + addFileElement( xmlDoc, elemFolder, usercdicfg, "CDI_VCD.CFG" ); + else + addFileElement( xmlDoc, elemFolder, locate( "data", "k3b/cdi/cdi_vcd.cfg" ), "CDI_VCD.CFG" ); + } + + // sequence-items element & segment-items element + QDomElement elemsequenceItems; + QDomElement elemsegmentItems; + + // sequence-item element & segment-item element + QDomElement elemsequenceItem; + QDomElement elemsegmentItem; + + // if we have segments, elemsegmentItems must be before any sequence in xml file order + if ( m_doc->vcdOptions()->haveSegments() ) + elemsegmentItems = addSubElement( xmlDoc, root, "segment-items" ); + + // sequence must always available ... + elemsequenceItems = addSubElement( xmlDoc, root, "sequence-items" ); + // if we have no sequence (photo (s)vcd) we must add a dummy sequence they inform the user to turn on pbc on there videoplayer + if ( !m_doc->vcdOptions()->haveSequence() ) { + QString filename; + if ( m_doc->vcdOptions()->mpegVersion() == 1 ) + filename = locate( "data", "k3b/extra/k3bphotovcd.mpg" ); + else + filename = locate( "data", "k3b/extra/k3bphotosvcd.mpg" ); + + elemsequenceItem = addSubElement( xmlDoc, elemsequenceItems, "sequence-item" ); + elemsequenceItem.setAttribute( "src", QString( "%1" ).arg( QFile::encodeName( filename ) ) ); + elemsequenceItem.setAttribute( "id", "sequence-000" ); + // default entry + QDomElement elemdefaultEntry; + elemdefaultEntry = addSubElement( xmlDoc, elemsequenceItem, "default-entry" ); + elemdefaultEntry.setAttribute( "id", "entry-000" ); + } + + + // pbc + QDomElement elemPbc; + + // Add Tracks to XML + QPtrListIterator it( *m_doc->tracks() ); + for ( ; it.current(); ++it ) { + if ( !it.current() ->isSegment() ) { + QString seqId = QString::number( it.current() ->index() ).rightJustify( 3, '0' ); + + elemsequenceItem = addSubElement( xmlDoc, elemsequenceItems, "sequence-item" ); + elemsequenceItem.setAttribute( "src", QString( "%1" ).arg( QFile::encodeName( it.current() ->absPath() ) ) ); + elemsequenceItem.setAttribute( "id", QString( "sequence-%1" ).arg( seqId ) ); + + // default entry + QDomElement elemdefaultEntry; + elemdefaultEntry = addSubElement( xmlDoc, elemsequenceItem, "default-entry" ); + elemdefaultEntry.setAttribute( "id", QString( "entry-%1" ).arg( seqId ) ); + + } else { + // sequence-items element needs at least one segment to fit the XML + elemsegmentItem = addSubElement( xmlDoc, elemsegmentItems, "segment-item" ); + elemsegmentItem.setAttribute( "src", QString( "%1" ).arg( QFile::encodeName( it.current() ->absPath() ) ) ); + elemsegmentItem.setAttribute( "id", QString( "segment-%1" ).arg( QString::number( it.current() ->index() ).rightJustify( 3, '0' ) ) ); + + } + } + for ( it.toFirst(); it.current(); ++it ) { + + if ( m_doc->vcdOptions() ->PbcEnabled() ) { + if ( elemPbc.isNull() ) + elemPbc = addSubElement( xmlDoc, root, "pbc" ); + + doPbc( xmlDoc, elemPbc, it.current() ); + } + } + + if ( ! elemPbc.isNull() ) { + QDomElement elemEndlist = addSubElement( xmlDoc, elemPbc, "endlist" ); + elemEndlist.setAttribute( "id", "end" ); + elemEndlist.setAttribute( "rejected", "true" ); + } + + m_xmlstring = xmlDoc.toString(); + kdDebug() << QString( "(K3bVcdXmlView) Write Data to %1:" ).arg( fname ) << endl; + + QFile xmlFile( fname ); + if ( xmlFile.open( IO_WriteOnly ) ) { + QTextStream ts( & xmlFile ); + ts << m_xmlstring; + xmlFile.close(); + return true; + } + + return false; +} + +void K3bVcdXmlView::addComment( QDomDocument& doc, QDomElement& parent, const QString& text ) +{ + QDomComment comment = doc.createComment( text ); + parent.appendChild( comment ); +} + +QDomElement K3bVcdXmlView::addSubElement( QDomDocument& doc, QDomElement& parent, const QString& name, const QString& value ) +{ + QDomElement element = doc.createElement( name ); + parent.appendChild( element ); + if ( !value.isNull() ) { + QDomText t = doc.createTextNode( value ); + element.appendChild( t ); + } + return element; +} + +QDomElement K3bVcdXmlView::addSubElement( QDomDocument& doc, QDomElement& parent, const QString& name, const int& value ) +{ + QDomElement element = doc.createElement( name ); + parent.appendChild( element ); + if ( value >= -1 ) { + QDomText t = doc.createTextNode( QString( "%1" ).arg( value ) ); + element.appendChild( t ); + } + return element; +} + +QDomElement K3bVcdXmlView::addFolderElement( QDomDocument& doc, QDomElement& parent, const QString& name ) +{ + QDomElement elemFolder = addSubElement( doc, parent, "folder" ); + addSubElement( doc, elemFolder, "name", name ); + + return elemFolder; +} + +void K3bVcdXmlView::addFileElement( QDomDocument& doc, QDomElement& parent, const QString& src, const QString& name, bool mixed ) +{ + QDomElement elemFile = addSubElement( doc, parent, "file" ); + elemFile.setAttribute( "src", QString( "%1" ).arg( src ) ); + if ( mixed ) + elemFile.setAttribute( "format", "mixed" ); + + addSubElement( doc, elemFile, "name", name ); +} + +void K3bVcdXmlView::doPbc( QDomDocument& doc, QDomElement& parent, K3bVcdTrack* track ) +{ + QString ref = ( track->isSegment() ) ? "segment" : "sequence"; + + QDomElement elemSelection = addSubElement( doc, parent, "selection" ); + elemSelection.setAttribute( "id", QString( "select-%1-%2" ).arg( ref ).arg( QString::number( track->index() ).rightJustify( 3, '0' ) ) ); + + setNumkeyBSN( doc, elemSelection, track ); + + for ( int i = 0; i < K3bVcdTrack::_maxPbcTracks; i++ ) { + QDomElement elemPbcSelectionPNRDT; + + if ( track->getPbcTrack( i ) ) { + int index = track->getPbcTrack( i ) ->index(); + QString ref = ( track->getPbcTrack( i ) ->isSegment() ) ? "segment" : "sequence"; + + switch ( i ) { + case K3bVcdTrack::PREVIOUS: + elemPbcSelectionPNRDT = addSubElement( doc, elemSelection, "prev" ); + elemPbcSelectionPNRDT.setAttribute( "ref", QString( "select-%1-%2" ).arg( ref ).arg( QString::number( index ).rightJustify( 3, '0' ) ) ); + break; + case K3bVcdTrack::NEXT: + elemPbcSelectionPNRDT = addSubElement( doc, elemSelection, "next" ); + elemPbcSelectionPNRDT.setAttribute( "ref", QString( "select-%1-%2" ).arg( ref ).arg( QString::number( index ).rightJustify( 3, '0' ) ) ); + break; + case K3bVcdTrack::RETURN: + elemPbcSelectionPNRDT = addSubElement( doc, elemSelection, "return" ); + elemPbcSelectionPNRDT.setAttribute( "ref", QString( "select-%1-%2" ).arg( ref ).arg( QString::number( index ).rightJustify( 3, '0' ) ) ); + break; + case K3bVcdTrack::DEFAULT: + elemPbcSelectionPNRDT = addSubElement( doc, elemSelection, "default" ); + elemPbcSelectionPNRDT.setAttribute( "ref", QString( "select-%1-%2" ).arg( ref ).arg( QString::number( index ).rightJustify( 3, '0' ) ) ); + break; + case K3bVcdTrack::AFTERTIMEOUT: + if ( track->getWaitTime() >= 0 ) { + elemPbcSelectionPNRDT = addSubElement( doc, elemSelection, "timeout" ); + elemPbcSelectionPNRDT.setAttribute( "ref", QString( "select-%1-%2" ).arg( ref ).arg( QString::number( index ).rightJustify( 3, '0' ) ) ); + } + break; + } + } else { + // jump to otherwise do noop while disabled + if ( track->getNonPbcTrack( i ) == K3bVcdTrack::VIDEOEND ) { + switch ( i ) { + case K3bVcdTrack::PREVIOUS: + elemPbcSelectionPNRDT = addSubElement( doc, elemSelection, "prev" ); + elemPbcSelectionPNRDT.setAttribute( "ref", "end" ); + break; + case K3bVcdTrack::NEXT: + elemPbcSelectionPNRDT = addSubElement( doc, elemSelection, "next" ); + elemPbcSelectionPNRDT.setAttribute( "ref", "end" ); + break; + case K3bVcdTrack::RETURN: + elemPbcSelectionPNRDT = addSubElement( doc, elemSelection, "return" ); + elemPbcSelectionPNRDT.setAttribute( "ref", "end" ); + break; + case K3bVcdTrack::DEFAULT: + elemPbcSelectionPNRDT = addSubElement( doc, elemSelection, "default" ); + elemPbcSelectionPNRDT.setAttribute( "ref", "end" ); + break; + case K3bVcdTrack::AFTERTIMEOUT: + if ( track->getWaitTime() >= 0 ) { + elemPbcSelectionPNRDT = addSubElement( doc, elemSelection, "timeout" ); + elemPbcSelectionPNRDT.setAttribute( "ref", "end" ); + } + break; + } + } + } + } + + addSubElement( doc, elemSelection, "wait", track->getWaitTime() ); + QDomElement loop = addSubElement( doc, elemSelection, "loop", track->getPlayTime() ); + if ( track->Reactivity() ) + loop.setAttribute( "jump-timing", "delayed" ); + else + loop.setAttribute( "jump-timing", "immediate" ); + + addSubElement( doc, elemSelection, "play-item" ).setAttribute( "ref", QString( "%1-%2" ).arg( ref ).arg( QString::number( track->index() ).rightJustify( 3, '0' ) ) ); + + setNumkeySEL( doc, elemSelection, track ); +} + +void K3bVcdXmlView::setNumkeyBSN( QDomDocument& doc, QDomElement& parent, K3bVcdTrack* track ) +{ + if ( track->PbcNumKeys() ) { + if ( track->PbcNumKeysUserdefined() ) { + QMap numKeyMap = track->DefinedNumKey(); + QMap::const_iterator trackIt; + + m_startkey = 0; + trackIt = numKeyMap.begin(); + if ( trackIt != numKeyMap.end() ) + m_startkey = trackIt.key(); + + if ( m_startkey > 0 ) + addSubElement( doc, parent, "bsn", m_startkey ); + else // user has no numKeys defined for this track + track->setPbcNumKeys( false ); + + } else { + // default start with key #1 + addSubElement( doc, parent, "bsn", 1 ); + } + } +} + +void K3bVcdXmlView::setNumkeySEL( QDomDocument& doc, QDomElement& parent, K3bVcdTrack* track ) +{ + if ( track->PbcNumKeys() ) { + QDomElement elemPbcSelectionNumKeySEL; + QString ref = ( track->isSegment() ) ? "segment" : "sequence"; + int none = m_startkey; + if ( track->PbcNumKeysUserdefined() ) { + QMap numKeyMap = track->DefinedNumKey(); + QMap::const_iterator trackIt; + + for ( trackIt = numKeyMap.begin(); trackIt != numKeyMap.end(); ++trackIt ) { + + kdDebug() << QString( "trackIt key: %1 none: %2" ).arg( trackIt.key() ).arg( none ) << endl; + while ( none < trackIt.key() ) { + elemPbcSelectionNumKeySEL = addSubElement( doc, parent, "select" ); + elemPbcSelectionNumKeySEL.setAttribute( "ref", QString( "select-%1-%2" ).arg( ref ).arg( QString::number( track->index() ).rightJustify( 3, '0' ) ) ); + addComment( doc, parent, QString( "key %1 -> %2 (normal none)" ).arg( none ).arg( QFile::encodeName( track->absPath() ) ) ); + none++; + } + + if ( trackIt.data() ) { + QString ref = ( trackIt.data() ->isSegment() ) ? "segment" : "sequence"; + elemPbcSelectionNumKeySEL = addSubElement( doc, parent, "select" ); + elemPbcSelectionNumKeySEL.setAttribute( "ref", QString( "select-%1-%2" ).arg( ref ).arg( QString::number( trackIt.data() ->index() ).rightJustify( 3, '0' ) ) ); + addComment( doc, parent, QString( "key %1 -> %2" ).arg( trackIt.key() ).arg( QFile::encodeName( trackIt.data() ->absPath() ) ) ); + } else { + elemPbcSelectionNumKeySEL = addSubElement( doc, parent, "select" ); + elemPbcSelectionNumKeySEL.setAttribute( "ref", "end" ); + addComment( doc, parent, QString( "key %1 -> end" ).arg( trackIt.key() ) ); + } + none++; + } + } else { + // default reference to itSelf + elemPbcSelectionNumKeySEL = addSubElement( doc, parent, "select" ); + elemPbcSelectionNumKeySEL.setAttribute( "ref", QString( "select-%1-%2" ).arg( ref ).arg( QString::number( track->index() ).rightJustify( 3, '0' ) ) ); + } + } +} + diff --git a/libk3b/projects/videocd/k3bvcdxmlview.h b/libk3b/projects/videocd/k3bvcdxmlview.h new file mode 100644 index 0000000..d99549b --- /dev/null +++ b/libk3b/projects/videocd/k3bvcdxmlview.h @@ -0,0 +1,59 @@ +/* +* +* $Id: k3bvcdxmlview.h 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* THX to Manfred Odenstein +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +#ifndef K3B_VCD_XMLVIEW_H +#define K3B_VCD_XMLVIEW_H + +#include +#include +#include + +#include + +class K3bVcdOptions; +class K3bVcdTrack; + + +class K3bVcdXmlView +{ + + public: + K3bVcdXmlView( K3bVcdDoc* ); + ~K3bVcdXmlView(); + + bool write( const QString& ); + QString xmlString() + { + return m_xmlstring; + } + + private: + QString m_xmlstring; + + void addComment( QDomDocument& doc, QDomElement& parent, const QString& text ); + QDomElement addSubElement( QDomDocument&, QDomElement&, const QString& name, const QString& value = QString::null ); + QDomElement addSubElement( QDomDocument&, QDomElement&, const QString& name, const int& value ); + + QDomElement addFolderElement( QDomDocument&, QDomElement&, const QString& name ); + void addFileElement( QDomDocument&, QDomElement&, const QString& src, const QString& name, bool mixed = false ); + void doPbc( QDomDocument&, QDomElement&, K3bVcdTrack* ); + void setNumkeyBSN( QDomDocument& , QDomElement&, K3bVcdTrack* ); + void setNumkeySEL( QDomDocument& , QDomElement&, K3bVcdTrack* ); + K3bVcdDoc* m_doc; + int m_startkey; +}; + +#endif diff --git a/libk3b/projects/videocd/mpeginfo/Makefile.am b/libk3b/projects/videocd/mpeginfo/Makefile.am new file mode 100644 index 0000000..af1b06b --- /dev/null +++ b/libk3b/projects/videocd/mpeginfo/Makefile.am @@ -0,0 +1,5 @@ +INCLUDES = $(all_includes) +noinst_LTLIBRARIES = libmpeginfo.la + +libmpeginfo_la_SOURCES = k3bmpeginfo.cpp + diff --git a/libk3b/projects/videocd/mpeginfo/k3bmpeginfo.cpp b/libk3b/projects/videocd/mpeginfo/k3bmpeginfo.cpp new file mode 100644 index 0000000..583a0aa --- /dev/null +++ b/libk3b/projects/videocd/mpeginfo/k3bmpeginfo.cpp @@ -0,0 +1,844 @@ +/* +* +* $Id: k3bmpeginfo.cpp 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +// kde includes +#include + +// k3b includes +#include "k3bmpeginfo.h" + +static const double frame_rates[ 16 ] = + { + 0.0, 24000.0 / 1001, 24.0, 25.0, + 30000.0 / 1001, 30.0, 50.0, 60000.0 / 1001, + 60.0, 0.0, + }; + +K3bMpegInfo::K3bMpegInfo( const char* filename ) + : m_mpegfile( 0 ), + m_filename( filename ), + m_done( false ), + m_buffstart( 0 ), + m_buffend( 0 ), + m_buffer( 0 ), + m_initial_TS( 0.0 ) +{ + + mpeg_info = new Mpeginfo(); + + m_mpegfile = fopen( filename, "rb" ); + + if ( m_mpegfile == 0 ) { + kdDebug() << QString( "Unable to open %1" ).arg( m_filename ) << endl; + return ; + } + + if ( fseeko( m_mpegfile, 0, SEEK_END ) ) { + kdDebug() << QString( "Unable to seek in file %1" ).arg( m_filename ) << endl; + return ; + } + + llong lof = ftello( m_mpegfile ); + + if ( lof == -1 ) { + kdDebug() << QString( "Seeking to end of input file %1 failed." ).arg( m_filename ) << endl; + //give up.. + return ; + } else + m_filesize = lof; + + // nothing to do on an empty file + if ( !m_filesize ) { + kdDebug() << QString( "File %1 is empty." ).arg( m_filename ) << endl; + m_error_string = i18n( "File %1 is empty." ).arg( m_filename ); + return ; + } + + m_buffer = new byte[ BUFFERSIZE ]; + + MpegParsePacket ( ); + +} + +K3bMpegInfo::~K3bMpegInfo() +{ + if ( m_buffer ) { + delete[] m_buffer; + } + if ( m_mpegfile ) { + fclose( m_mpegfile ); + } + + delete mpeg_info; +} +bool K3bMpegInfo::MpegParsePacket () +{ + + /* verify the packet begins with a pack header */ + if ( !EnsureMPEG( 0, MPEG_PACK_HEADER_CODE ) ) { + llong code = GetNBytes( 0, 4 ); + + kdDebug() << QString( "(K3bMpegInfo::mpeg_parse_packet ()) pack header code 0x%1 expected, but 0x%2 found" ).arg( 0x00000100 + MPEG_PACK_HEADER_CODE, 0, 16 ).arg( code, 0, 16 ) << endl; + + if ( code == 0x00000100 + MPEG_SEQUENCE_CODE ) { + kdDebug() << "...this looks like a elementary video stream but a multiplexed program stream was required." << endl; + m_error_string = i18n( "This looks like a elementary video stream but a multiplexed program stream was required." ); + } + + if ( ( 0xfff00000 & code ) == 0xfff00000 ) { + kdDebug() << "...this looks like a elementary audio stream but a multiplexed program stream was required." << endl; + m_error_string = i18n( "This looks like a elementary audio stream but a multiplexed program stream was required." ); + } + + if ( code == 0x52494646 ) { + kdDebug() << "...this looks like a RIFF header but a plain multiplexed program stream was required." << endl; + m_error_string = i18n( "This looks like a RIFF header but a plain multiplexed program stream was required." ); + } + + return false; + } + + + /* take a look at the pack header */ + int offset = 0; + while ( GetByte( offset ) == 0x00 ) + offset ++; + //here we're on the first non null byte let's get back to leave two zeros (packet start code) + offset -= 2; + + if ( offset != 0 ) { + // we actually skipped some zeroes + kdDebug() << QString( "Skipped %1 zeroes at start of file" ).arg( offset ) << endl; + } + + // here while schleife + while ( offset != -1 ) { + offset = MpegParsePacket( offset ); + } + + /* + int pkt = 0; + offset = FindNextMarker( 0, MPEG_PACK_HEADER_CODE ); + + while ( offset != -1 ) { + pkt++; + offset = FindNextMarker( offset+1, MPEG_PACK_HEADER_CODE ); + } + + kdDebug() << "Pkt found: " << pkt << endl; + */ + + //seek the file duration by fetching the last PACK + //and reading its timestamp + llong last_pack = bdFindNextMarker( m_filesize - 13, MPEG_PACK_HEADER_CODE ); + // -12 because a PACK is at least 12 bytes + double duration; + last_pack += 4; + int bits = GetByte( last_pack ) >> 4; + + if ( bits == 0x2 ) /* %0010 ISO11172-1 */ + { + duration = ReadTS( last_pack ); + } else if ( bits >> 2 == 0x1 ) /* %01xx ISO13818-1 */ + { + duration = ReadTSMpeg2( last_pack ); + } else { + kdDebug() << QString( "no timestamp found" ) << endl; + duration = ReadTS( last_pack ); + } + + mpeg_info->playing_time = duration - m_initial_TS; + + + if ( !mpeg_info->has_video ) + for ( int i = 0; i < 2; i++ ) + if ( mpeg_info->video[ i ].seen ) + mpeg_info->has_video = true; + + if ( !mpeg_info->has_audio ) + for ( int i = 0; i < 2; i++ ) + if ( mpeg_info->audio[ i ].seen ) + mpeg_info->has_audio = true; + + return true; +} + +llong K3bMpegInfo::MpegParsePacket ( llong offset ) +{ + byte mark = 0; + uint size = 0; + + /* continue until start code seen */ + offset = FindNextMarker( offset, &mark ); + + if ( offset < 0 ) + return offset; + + switch ( mark ) { + int bits; + + case MPEG_PACK_HEADER_CODE: + // kdDebug() << QString( "MPEG_PACK_HEADER_CODE @ %1" ).arg( offset ) << endl; + + offset += 4; + + if ( mpeg_info->version != MPEG_VERS_INVALID ) + break; + + bits = GetByte( offset ) >> 4; + + if ( bits == 0x2 ) /* %0010 ISO11172-1 */ + { + mpeg_info->version = MPEG_VERS_MPEG1; + + unsigned long muxrate = 0; + + muxrate = ( GetByte( offset + 5 ) & 0x7F ) << 15; + muxrate |= ( GetByte( offset + 6 ) << 7 ); + muxrate |= ( GetByte( offset + 7 ) >> 1 ); + + mpeg_info->muxrate = muxrate * 50 * 8; + + if ( m_initial_TS == 0.0 ) + { + m_initial_TS = ReadTS( offset ); + kdDebug() << QString( "Initial TS = %1" ).arg( m_initial_TS ) << endl; + } + + } else if ( bits >> 2 == 0x1 ) /* %01xx ISO13818-1 */ + { + mpeg_info->version = MPEG_VERS_MPEG2; + + unsigned long muxrate = 0; + muxrate = GetByte( offset + 6 ) << 14; + muxrate |= GetByte( offset + 7 ) << 6; + muxrate |= GetByte( offset + 8 ) >> 2; + + mpeg_info->muxrate = muxrate * 50 * 8; + + if ( m_initial_TS == 0.0 ) + { + m_initial_TS = ReadTSMpeg2( offset ); + kdDebug() << QString( "Initial TS = %1" ).arg( m_initial_TS ) << endl; + } + + } else { + kdDebug() << QString( "packet not recognized as either version 1 or 2 (%1)" ).arg( bits ) << endl; + mpeg_info->version = MPEG_VERS_INVALID; + return -1; + } + break; + + case MPEG_SYSTEM_HEADER_CODE: + case MPEG_PAD_CODE: + case MPEG_PRIVATE_1_CODE: + case MPEG_VIDEO_E0_CODE: + case MPEG_VIDEO_E1_CODE: + case MPEG_VIDEO_E2_CODE: + case MPEG_AUDIO_C0_CODE: + case MPEG_AUDIO_C1_CODE: + case MPEG_AUDIO_C2_CODE: + + offset += 4; + size = GetSize( offset ); + offset += 2; + // kdDebug() << QString( "offset = %1, size = %2" ).arg( offset ).arg( size ) << endl; + + switch ( mark ) { + case MPEG_SYSTEM_HEADER_CODE: + // kdDebug() << QString( "Systemheader: %1" ).arg( m_code, 0, 16 ) << endl; + break; + + case MPEG_VIDEO_E0_CODE: + case MPEG_VIDEO_E1_CODE: + case MPEG_VIDEO_E2_CODE: + ParseVideo( offset, mark ); + // _analyze_video_pes (code & 0xff, buf + pos, size, !parse_pes, ctx); + if ( mpeg_info->has_video && mpeg_info->has_audio ) { + return -1; + } else if ( mark == MPEG_VIDEO_E0_CODE || mpeg_info->version == MPEG_VERS_MPEG2 && mark == MPEG_VIDEO_E1_CODE || mpeg_info->version == MPEG_VERS_MPEG1 && mark == MPEG_VIDEO_E2_CODE ) { + mpeg_info->has_video = true; + offset = FindNextAudio( offset ); + } + break; + case MPEG_AUDIO_C0_CODE: + case MPEG_AUDIO_C1_CODE: + case MPEG_AUDIO_C2_CODE: + offset = SkipPacketHeader( offset - 6 ); + ParseAudio( offset, mark ); + // audio packet doesn't begin with 0xFFF + if ( !mpeg_info->audio[ GetAudioIdx( mark ) ].seen ) { + int a_idx = GetAudioIdx( mark ); + while ( ( offset < m_filesize - 10 ) && !mpeg_info->audio[ a_idx ].seen ) { + if ( ( GetByte( offset ) == 0xFF ) && ( GetByte( offset + 1 ) & 0xF0 ) == 0xF0 ) + ParseAudio( offset, mark ); + offset++; + } + } + + mpeg_info->has_audio = true; + if ( mpeg_info->has_video ) + return -1; + + offset = FindNextVideo( offset ); + break; + + case MPEG_PRIVATE_1_CODE: + kdDebug() << QString( "PrivateCode: %1" ).arg( mark, 0, 16 ) << endl; + break; + } + break; + + case MPEG_PROGRAM_END_CODE: + kdDebug() << QString( "ProgramEndCode: %1" ).arg( mark, 0, 16 ) << endl; + offset += 4; + break; + + case MPEG_PICTURE_CODE: + kdDebug() << QString( "PictureCode: %1" ).arg( mark, 0, 16 ) << endl; + offset += 3; + break; + + default: + offset += 4; + break; + } + + return offset; +} + +byte K3bMpegInfo::GetByte( llong offset ) +{ + unsigned long nread; + if ( ( offset >= m_buffend ) || ( offset < m_buffstart ) ) { + + if ( fseeko( m_mpegfile, offset, SEEK_SET ) ) { + kdDebug() << QString( "could not get seek to offset (%1) in file %2 (size:%3)" ).arg( offset ).arg( m_filename ).arg( m_filesize ) << endl; + return 0x11; + } + nread = fread( m_buffer, 1, BUFFERSIZE, m_mpegfile ); + m_buffstart = offset; + m_buffend = offset + nread; + if ( ( offset >= m_buffend ) || ( offset < m_buffstart ) ) { + // weird + kdDebug() << QString( "could not get offset %1 in file %2 [%3]" ).arg( offset ).arg( m_filename ).arg( m_filesize ) << endl; + return 0x11; + } + } + return m_buffer[ offset - m_buffstart ]; +} + +// same as above but improved for backward search +byte K3bMpegInfo::bdGetByte( llong offset ) +{ + unsigned long nread; + if ( ( offset >= m_buffend ) || ( offset < m_buffstart ) ) { + llong start = offset - BUFFERSIZE + 1 ; + start = start >= 0 ? start : 0; + + fseeko( m_mpegfile, start, SEEK_SET ); + + nread = fread( m_buffer, 1, BUFFERSIZE, m_mpegfile ); + m_buffstart = start; + m_buffend = start + nread; + if ( ( offset >= m_buffend ) || ( offset < m_buffstart ) ) { + // weird + kdDebug() << QString( "could not get offset %1 in file %2 [%3]" ).arg( offset ).arg( m_filename ).arg( m_filesize ) << endl; + + return 0x11; + } + } + return m_buffer[ offset - m_buffstart ]; +} + + +llong K3bMpegInfo::GetNBytes( llong offset, int n ) +{ + llong nbytes = 0; + n--; + for ( int i = 0; i < n; i++ ) + ( ( char* ) & nbytes ) [ n - i ] = GetByte( offset + i ); + + return nbytes; + +} + +// get a two byte size +unsigned short int K3bMpegInfo::GetSize( llong offset ) +{ + return GetByte( offset ) * 256 + GetByte( offset + 1 ); + // return GetNBytes( offset, 2 ); + +} + +bool K3bMpegInfo::EnsureMPEG( llong offset, byte mark ) +{ + if ( ( GetByte( offset ) == 0x00 ) && + ( GetByte( offset + 1 ) == 0x00 ) && + ( GetByte( offset + 2 ) == 0x01 ) && + ( GetByte( offset + 3 ) == mark ) ) + return true; + else + return false; +} + + +// find next 0x 00 00 01 xx sequence, returns offset or -1 on err +llong K3bMpegInfo::FindNextMarker( llong from ) +{ + llong offset; + for ( offset = from; offset < ( m_filesize - 4 ); offset++ ) { + if ( + ( GetByte( offset + 0 ) == 0x00 ) && + ( GetByte( offset + 1 ) == 0x00 ) && + ( GetByte( offset + 2 ) == 0x01 ) ) { + return offset; + } + } + return -1; +} + +// find next 0x 00 00 01 xx sequence, returns offset or -1 on err and +// change mark to xx +llong K3bMpegInfo::FindNextMarker( llong from, byte* mark ) +{ + llong offset = FindNextMarker( from ); + if ( offset >= 0 ) { + *mark = GetByte( offset + 3 ); + return offset; + } else { + return -1; + } +} + +// find next 0X00 00 01 mark +llong K3bMpegInfo::FindNextMarker( llong from, byte mark ) +{ + llong offset = from; + while ( offset >= 0 ) { + offset = FindNextMarker( offset ); + if ( offset < 0 ) { + return -1; + } + if ( EnsureMPEG( offset, mark ) ) { + return offset; + } else + offset++; + } + + //shouldn't be here + return -1; +} + +llong K3bMpegInfo::bdFindNextMarker( llong from, byte mark ) +{ + llong offset; + for ( offset = from; offset >= 0; offset-- ) { + if ( + ( bdGetByte( offset ) == 0x00 ) && + ( bdGetByte( offset + 1 ) == 0x00 ) && + ( bdGetByte( offset + 2 ) == 0x01 ) && + ( bdGetByte( offset + 3 ) == mark ) ) { + return offset; + } + } + return -1; +} + +llong K3bMpegInfo::bdFindNextMarker( llong from, byte* mark ) +{ + llong offset; + for ( offset = from; offset >= 0; offset-- ) { + if ( ( bdGetByte( offset ) == 0x00 ) && + ( bdGetByte( offset + 1 ) == 0x00 ) && + ( bdGetByte( offset + 2 ) == 0x01 ) ) { + *mark = bdGetByte( offset + 3 ); + return offset; + } + } + return -1; + +} + +llong K3bMpegInfo::FindNextVideo( llong from ) +{ + llong offset = from; + while ( offset >= 0 ) { + offset = FindNextMarker( offset ); + if ( offset < 0 ) { + return -1; + } + if ( EnsureMPEG( offset, MPEG_VIDEO_E0_CODE ) || EnsureMPEG( offset, MPEG_VIDEO_E1_CODE ) || EnsureMPEG( offset, MPEG_VIDEO_E2_CODE ) ) { + return offset; + } else + offset++; + } + + //shouldn't be here + return -1; +} + +llong K3bMpegInfo::FindNextAudio( llong from ) +{ + llong offset = from; + while ( offset >= 0 ) { + offset = FindNextMarker( offset ); + if ( offset < 0 ) { + return -1; + } + if ( EnsureMPEG( offset, MPEG_AUDIO_C0_CODE ) || EnsureMPEG( offset, MPEG_AUDIO_C1_CODE ) || EnsureMPEG( offset, MPEG_AUDIO_C2_CODE ) ) { + return offset; + } else + offset++; + } + + return -1; +} + + +int K3bMpegInfo::GetVideoIdx ( byte marker ) +{ + switch ( marker ) { + case MPEG_VIDEO_E0_CODE: + return 0; + break; + + case MPEG_VIDEO_E1_CODE: + return 1; + break; + + case MPEG_VIDEO_E2_CODE: + return 2; + break; + + default: + kdDebug() << "VideoCode not reached" << endl; + break; + } + + return -1; +} + +int K3bMpegInfo::GetAudioIdx ( byte marker ) +{ + switch ( marker ) { + case MPEG_AUDIO_C0_CODE: + return 0; + break; + + case MPEG_AUDIO_C1_CODE: + return 1; + break; + + case MPEG_AUDIO_C2_CODE: + return 2; + break; + + default: + kdDebug() << "VideoCode not reached" << endl; + break; + } + + return -1; +} + +llong K3bMpegInfo::SkipPacketHeader( llong offset ) +{ + byte tmp_byte; + if ( mpeg_info->version == MPEG_VERS_MPEG1 ) { + // skip startcode and packet size + offset += 6; + //remove stuffing bytes + tmp_byte = GetByte( offset ); + while ( tmp_byte & 0x80 ) + tmp_byte = GetByte( ++offset ); + + if ( ( tmp_byte & 0xC0 ) == 0x40 ) // next two bits are 01 + offset += 2; + + tmp_byte = GetByte( offset ); + if ( ( tmp_byte & 0xF0 ) == 0x20 ) + offset += 5; + else if ( ( tmp_byte & 0xF0 ) == 0x30 ) + offset += 10; + else + offset++; + + return offset; + } else if ( mpeg_info->version == MPEG_VERS_MPEG2 ) { + return ( offset + 9 + GetByte( offset + 8 ) ); + } else + return ( offset + 10 ); +} + +void K3bMpegInfo::ParseAudio ( llong offset, byte marker ) +{ + unsigned brate, srate; + bool mpeg2_5 = false; + + const int a_idx = GetAudioIdx( marker ); + + if ( mpeg_info->audio[ a_idx ].seen ) /* we have it already */ + return ; + + if ( ( GetByte( offset ) != 0xFF ) || ( ( GetByte( offset + 1 ) & 0xF0 ) != 0xF0 ) ) { + // doesn't start with 12 bits set + if ( ( GetByte( offset ) != 0xFF ) || ( ( GetByte( offset + 1 ) & 0xE0 ) != 0xE0 ) ) { + // doesn't start with 11 bits set + return ; + } else { + // start with 11 bits set + mpeg2_5 = true; + } + } + + // Find mpeg version 1.0 or 2.0 + if ( GetByte( offset + 1 ) & 0x08 ) { + if ( !mpeg2_5 ) + mpeg_info->audio[ a_idx ].version = 1; + else + return ; // invalid 01 encountered + } else { + if ( !mpeg2_5 ) + mpeg_info->audio[ a_idx ].version = 2; + else + mpeg_info->audio[ a_idx ].version = 3; //for mpeg 2.5 + } + + // Find Layer + mpeg_info->audio[ a_idx ].layer = ( GetByte( offset + 1 ) & 0x06 ) >> 1; + switch ( mpeg_info->audio[ a_idx ].layer ) { + case 0: + mpeg_info->audio[ a_idx ].layer = 0; + break; + case 1: + mpeg_info->audio[ a_idx ].layer = 3; + break; + case 2: + mpeg_info->audio[ a_idx ].layer = 2; + break; + case 3: + mpeg_info->audio[ a_idx ].layer = 1; + break; + } + + // Protection Bit + mpeg_info->audio[ a_idx ].protect = GetByte( offset + 1 ) & 0x01; + if ( mpeg_info->audio[ a_idx ].protect ) + mpeg_info->audio[ a_idx ].protect = 0; + else + mpeg_info->audio[ a_idx ].protect = 1; + + const unsigned bit_rates[ 4 ][ 16 ] = { + { + 0, + }, + {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0}, + {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0}, + {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0} + }; + + + /* const unsigned bit_rates [ 3 ][ 3 ][ 16 ] = { + { + {0, }, + {0, }, + {0, }, + }, + { + {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0}, + {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0}, + {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0} + }, + { + {0, 32, 48, 56, 64, 80 , 96 , 112, 128, 144, 160, 176, 192, 224, 256, 0}, + {0, 8, 16, 24, 32, 40, 48, 56, 64 , 80 , 96 , 112, 128, 144, 160, 0}, + {0, 8, 16, 24, 32, 40, 48, 56, 64 , 80 , 96 , 112, 128, 144, 160, 0} + } + }; + */ + + const unsigned sampling_rates[ 4 ][ 4 ] = { + { + 0, + }, + {44100, 48000, 32000, 0}, //mpeg 1 + {22050, 24000, 16000, 0}, //mpeg 2 + {11025, 12000, 8000, 0} //mpeg 2.5 + }; + + + // Bitrate index and sampling index to pass through the array + brate = GetByte( offset + 2 ) >> 4; + srate = ( GetByte( offset + 2 ) & 0x0f ) >> 2; + + mpeg_info->audio[ a_idx ].bitrate = 1024 * bit_rates[ mpeg_info->audio[ a_idx ].layer ][ brate ]; + mpeg_info->audio[ a_idx ].byterate = ( float ) ( mpeg_info->audio[ a_idx ].bitrate / 8.0 ); + mpeg_info->audio[ a_idx ].sampfreq = sampling_rates[ mpeg_info->audio[ a_idx ].version ][ srate ]; + + // Audio mode + mpeg_info->audio[ a_idx ].mode = 1 + ( GetByte( offset + 3 ) >> 6 ) ; + + // Copyright bit + if ( GetByte( offset + 3 ) & 0x08 ) + mpeg_info->audio[ a_idx ].copyright = true; + else + mpeg_info->audio[ a_idx ].copyright = false; + + // Original/Copy bit + if ( GetByte( offset + 3 ) & 0x04 ) + mpeg_info->audio[ a_idx ].original = true; + else + mpeg_info->audio[ a_idx ].original = false; + + + mpeg_info->audio[ a_idx ].seen = true; +} + +void K3bMpegInfo::ParseVideo ( llong offset, byte marker ) +{ + unsigned long aratio, frate, brate; + + const int v_idx = GetVideoIdx( marker ); + + const double aspect_ratios[ 16 ] = { + 0.0000, 1.0000, 0.6735, 0.7031, + 0.7615, 0.8055, 0.8437, 0.8935, + 0.9375, 0.9815, 1.0255, 1.0695, + 1.1250, 1.1575, 1.2015, 0.0000 + }; + + if ( mpeg_info->video[ v_idx ].seen ) /* we have it already */ + return ; + + offset = FindNextMarker( offset + 1, MPEG_SEQUENCE_CODE ); + + if ( !offset ) + return ; + + offset += 4; + + mpeg_info->video[ v_idx ].hsize = GetSize( offset ) >> 4; + mpeg_info->video[ v_idx ].vsize = GetSize( offset + 1 ) & 0x0FFF; + + // Get picture rate + offset += 3; // after picture sizes + + aratio = ( GetByte( offset ) & 0x0F ) >> 4; + mpeg_info->video[ v_idx ].aratio = aspect_ratios[ aratio ]; + + // offset += 3; // after picture sizes + frate = GetByte( offset ) & 0x0F; + mpeg_info->video[ v_idx ].frate = frame_rates[ frate ]; + + offset += 1; // after picture rate + + // 18 following bytes are the bitrate /400 + + //read first 16 bytes + brate = GetSize( offset ); + // scale + brate <<= 2; + byte lasttwo = GetByte( offset + 2 ); + lasttwo >>= 6; + brate |= lasttwo; + + mpeg_info->video[ v_idx ].bitrate = 400 * brate; + + byte mark; + while ( true ) { + offset = FindNextMarker( offset, &mark ); + if ( mark == MPEG_GOP_CODE ) + break; + switch ( GetByte( offset + 3 ) ) { + case MPEG_EXT_CODE : + // Extension + offset += 4; + switch ( GetByte( offset ) >> 4 ) { + case 1: + //SequenceExt + if ( GetByte( offset + 1 ) & 0x08 ) + mpeg_info->video[ v_idx ].progressive = true; + mpeg_info->video[ v_idx ].chroma_format = ( GetByte( offset + 1 ) & 0x06 ) >> 1; + break; + case 2: + // SequenceDisplayExt + mpeg_info->video[ v_idx ].video_format = ( GetByte( offset ) & 0x0E ) >> 1; + break; + } + + break; + case MPEG_USER_CODE : + // UserData + break; + } + offset++; + } + + mpeg_info->video[ v_idx ].seen = true; +} + +double K3bMpegInfo::ReadTS( llong offset ) +{ + byte highbit; + unsigned long low4Bytes; + double TS; + + highbit = ( GetByte( offset ) >> 3 ) & 0x01; + + low4Bytes = ( ( GetByte( offset ) >> 1 ) & 0x03 ) << 30; + low4Bytes |= GetByte( offset + 1 ) << 22; + low4Bytes |= ( GetByte( offset + 2 ) >> 1 ) << 15; + low4Bytes |= GetByte( offset + 3 ) << 7; + low4Bytes |= GetByte( offset + 4 ) >> 1; + + + TS = ( double ) ( highbit * FLOAT_0x10000 * FLOAT_0x10000 ); + TS += ( double ) ( low4Bytes ); + TS /= ( double ) ( STD_SYSTEM_CLOCK_FREQ ); + + return TS; +} + +double K3bMpegInfo::ReadTSMpeg2( llong offset ) +{ + byte highbit; + unsigned long low4Bytes; + unsigned long sys_clock_ref; + double TS; + + highbit = ( GetByte( offset ) & 0x20 ) >> 5; + + low4Bytes = ( ( GetByte( offset ) & 0x18 ) >> 3 ) << 30; + low4Bytes |= ( GetByte( offset ) & 0x03 ) << 28; + low4Bytes |= GetByte( offset + 1 ) << 20; + low4Bytes |= ( GetByte( offset + 2 ) & 0xF8 ) << 12; + low4Bytes |= ( GetByte( offset + 2 ) & 0x03 ) << 13; + low4Bytes |= GetByte( offset + 3 ) << 5; + low4Bytes |= ( GetByte( offset + 4 ) ) >> 3; + + sys_clock_ref = ( GetByte( offset + 4 ) & 0x3 ) << 7; + sys_clock_ref |= ( GetByte( offset + 5 ) >> 1 ); + + TS = ( double ) ( highbit * FLOAT_0x10000 * FLOAT_0x10000 ); + TS += ( double ) ( low4Bytes ); + if ( sys_clock_ref == 0 ) + TS /= ( double ) ( STD_SYSTEM_CLOCK_FREQ ); + else { + TS /= ( double ) ( 27000000 / sys_clock_ref ); + } + + return TS; +} diff --git a/libk3b/projects/videocd/mpeginfo/k3bmpeginfo.h b/libk3b/projects/videocd/mpeginfo/k3bmpeginfo.h new file mode 100644 index 0000000..3436214 --- /dev/null +++ b/libk3b/projects/videocd/mpeginfo/k3bmpeginfo.h @@ -0,0 +1,178 @@ +/* +* +* $Id: k3bmpeginfo.h 619556 2007-01-03 17:38:12Z trueg $ +* Copyright (C) 2003-2004 Christian Kvasny +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* See the file "COPYING" for the exact licensing terms. +*/ + +#ifndef K3BMPEGINFO +#define K3BMPEGINFO + +#include + +// #define BUFFERSIZE 16384 +#define BUFFERSIZE 65536 + +#define MPEG_START_CODE_PATTERN ((ulong) 0x00000100) +#define MPEG_START_CODE_MASK ((ulong) 0xffffff00) + +#define MPEG_PICTURE_CODE ((ulong) 0x00000100) +/* [...slice codes... 0x1a7] */ + +#define MPEG_USER_CODE ((uchar) 0xb2) +#define MPEG_SEQUENCE_CODE ((uchar) 0xb3) +#define MPEG_EXT_CODE ((uchar) 0xb5) +#define MPEG_SEQ_END_CODE ((uchar) 0xb7) +#define MPEG_GOP_CODE ((uchar) 0xb8) +#define MPEG_PROGRAM_END_CODE ((uchar) 0xb9) +#define MPEG_PACK_HEADER_CODE ((uchar) 0xba) +#define MPEG_SYSTEM_HEADER_CODE ((uchar) 0xbb) +#define MPEG_PRIVATE_1_CODE ((uchar) 0xbd) +#define MPEG_PAD_CODE ((uchar) 0xbe) + +#define MPEG_AUDIO_C0_CODE ((uchar) 0xc0) /* default */ +#define MPEG_AUDIO_C1_CODE ((uchar) 0xc1) /* 2nd audio stream id (dual channel) */ +#define MPEG_AUDIO_C2_CODE ((uchar) 0xc2) /* 3rd audio stream id (surround sound) */ + +#define MPEG_VIDEO_E0_CODE ((uchar) 0xe0) /* motion */ +#define MPEG_VIDEO_E1_CODE ((uchar) 0xe1) /* lowres still */ +#define MPEG_VIDEO_E2_CODE ((uchar) 0xe2) /* hires still */ + +#define FLOAT_0x10000 (double)((unsigned long)1 << 16) +#define STD_SYSTEM_CLOCK_FREQ (unsigned long)90000 + +typedef unsigned char byte; +typedef long long llong; + +#include + +class video_info +{ + public: + bool seen; + unsigned long hsize; + unsigned long vsize; + double aratio; + double frate; + unsigned long bitrate; + unsigned long vbvsize; + bool progressive; + unsigned char video_format; + unsigned char chroma_format; + bool constrained_flag; +}; + +class audio_info +{ + public: + bool seen; + unsigned int version; + unsigned int layer; + unsigned int protect; + unsigned long bitrate; + float byterate; + unsigned long sampfreq; + int mode; + bool copyright; + bool original; +}; + +class Mpeginfo +{ + + public: + Mpeginfo() + : version( 0 ), + muxrate( 0 ), + playing_time( 0 ), + has_video ( false ), + has_audio ( false ) + { + for ( int i = 0; i < 3; i++ ) { + video[ i ].seen = false; + audio[ i ].seen = false; + } + }; + + ~Mpeginfo() + {} + ; + + unsigned int version; + unsigned long muxrate; + double playing_time; + bool has_video; + bool has_audio; + video_info video[ 3 ]; + audio_info audio[ 3 ]; +}; + +class K3bMpegInfo +{ + public: + K3bMpegInfo( const char* filename ); + ~K3bMpegInfo(); + enum mpeg_version { MPEG_VERS_INVALID = 0, MPEG_VERS_MPEG1 = 1, MPEG_VERS_MPEG2 = 2 }; + enum mode { MPEG_STEREO = 1, MPEG_JOINT_STEREO, MPEG_DUAL_CHANNEL, MPEG_SINGLE_CHANNEL }; + + const int version() + { + return mpeg_info->version; + }; + const QString error_string() + { + return m_error_string; + }; + Mpeginfo* mpeg_info; + + + private: + // General ToolBox + byte GetByte( llong offset ); + byte bdGetByte( llong offset ); + llong GetNBytes( llong, int ); + unsigned short int GetSize( llong offset ); + llong FindNextMarker( llong ); + llong FindNextMarker( llong, byte* ); + llong FindNextMarker( llong, byte ); + llong bdFindNextMarker( llong, byte ); + llong bdFindNextMarker( llong, byte* ); + llong FindNextVideo( llong ); + llong FindNextAudio( llong ); + + int GetVideoIdx ( byte ); + int GetAudioIdx ( byte ); + bool EnsureMPEG( llong, byte ); + void ParseVideo ( llong, byte ); + void ParseAudio ( llong, byte ); + bool MpegParsePacket (); + llong MpegParsePacket ( llong ); + llong SkipPacketHeader( llong ); + + double ReadTS( llong offset ); + double ReadTSMpeg2( llong offset ); + + FILE* m_mpegfile; + + const char* m_filename; + llong m_filesize; + + bool m_done; + + llong m_buffstart; + llong m_buffend; + byte* m_buffer; + double m_initial_TS; + QString m_error_string; + +}; + +#endif //K3bMpegInfo diff --git a/libk3b/projects/videodvd/Makefile.am b/libk3b/projects/videodvd/Makefile.am new file mode 100644 index 0000000..1b3e92b --- /dev/null +++ b/libk3b/projects/videodvd/Makefile.am @@ -0,0 +1,20 @@ +# we need the ../datacd for the uic generated header files +AM_CPPFLAGS= -I$(srcdir)/../../core \ + -I$(srcdir)/../../../libk3bdevice \ + -I$(srcdir)/../../../src \ + -I$(srcdir)/../../tools \ + -I$(srcdir)/../datadvd \ + -I$(srcdir)/../datacd \ + -I$(srcdir)/.. \ + -I../datacd \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libvideodvd.la + +libvideodvd_la_SOURCES = k3bvideodvddoc.cpp \ + k3bvideodvdjob.cpp \ + k3bvideodvdimager.cpp + +include_HEADERS = k3bvideodvddoc.h k3bvideodvdjob.h diff --git a/libk3b/projects/videodvd/k3bvideodvddoc.cpp b/libk3b/projects/videodvd/k3bvideodvddoc.cpp new file mode 100644 index 0000000..2f02ac6 --- /dev/null +++ b/libk3b/projects/videodvd/k3bvideodvddoc.cpp @@ -0,0 +1,71 @@ +/* + * + * $Id: k3bvideodvddoc.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bvideodvddoc.h" +#include "k3bvideodvdjob.h" + +#include + +#include + +#include + + +K3bVideoDvdDoc::K3bVideoDvdDoc( QObject* parent ) + : K3bDvdDoc( parent ) +{ +} + + +K3bVideoDvdDoc::~K3bVideoDvdDoc() +{ +} + + +bool K3bVideoDvdDoc::newDocument() +{ + if( K3bDataDoc::newDocument() ) { + + // K3bDataDoc::newDocument already deleted m_videoTsDir (again: bad design!) + m_videoTsDir = new K3bDirItem( "VIDEO_TS", this, root() ); + m_videoTsDir->setRemoveable(false); + m_videoTsDir->setRenameable(false); + m_videoTsDir->setMoveable(false); + m_videoTsDir->setHideable(false); + + K3bDirItem* audioTsDir = new K3bDirItem( "AUDIO_TS", this, root() ); + audioTsDir->setRemoveable(false); + audioTsDir->setRenameable(false); + audioTsDir->setMoveable(false); + audioTsDir->setHideable(false); + + setMultiSessionMode( NONE ); + + setModified( false ); + + return true; + } + else + return false; +} + + +K3bBurnJob* K3bVideoDvdDoc::newBurnJob( K3bJobHandler* hdl, QObject* parent ) +{ + return new K3bVideoDvdJob( this, hdl, parent ); +} + +//#include "k3bdvddoc.moc" diff --git a/libk3b/projects/videodvd/k3bvideodvddoc.h b/libk3b/projects/videodvd/k3bvideodvddoc.h new file mode 100644 index 0000000..034ae4d --- /dev/null +++ b/libk3b/projects/videodvd/k3bvideodvddoc.h @@ -0,0 +1,46 @@ +/* + * + * $Id: k3bvideodvddoc.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VIDEODVD_DOC_H_ +#define _K3B_VIDEODVD_DOC_H_ + +#include +#include "k3b_export.h" +class KConfig; + +class LIBK3B_EXPORT K3bVideoDvdDoc : public K3bDvdDoc +{ + public: + K3bVideoDvdDoc( QObject* parent = 0 ); + virtual ~K3bVideoDvdDoc(); + + virtual int type() const { return VIDEODVD; } + + virtual K3bBurnJob* newBurnJob( K3bJobHandler* hdl, QObject* parent ); + + virtual bool newDocument(); + + K3bDirItem* videoTsDir() const { return m_videoTsDir; } + + // TODO: implement load- and saveDocumentData since we do not need all those options + + protected: + virtual QString typeString() const { return "video_dvd"; } + + private: + K3bDirItem* m_videoTsDir; +}; + +#endif diff --git a/libk3b/projects/videodvd/k3bvideodvdimager.cpp b/libk3b/projects/videodvd/k3bvideodvdimager.cpp new file mode 100644 index 0000000..7362aa0 --- /dev/null +++ b/libk3b/projects/videodvd/k3bvideodvdimager.cpp @@ -0,0 +1,221 @@ +/* + * + * $Id: k3bvideodvdimager.cpp 633751 2007-02-15 08:22:49Z trueg $ + * Copyright (C) 2004-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bvideodvdimager.h" +#include "k3bvideodvddoc.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + + +class K3bVideoDvdImager::Private +{ +public: + K3bVideoDvdDoc* doc; + + QString tempPath; +}; + + +K3bVideoDvdImager::K3bVideoDvdImager( K3bVideoDvdDoc* doc, K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bIsoImager( doc, jh, parent, name ) +{ + d = new Private; + d->doc = doc; +} + + +K3bVideoDvdImager::~K3bVideoDvdImager() +{ + delete d; +} + + +void K3bVideoDvdImager::start() +{ + fixVideoDVDSettings(); + K3bIsoImager::start(); +} + + +void K3bVideoDvdImager::init() +{ + fixVideoDVDSettings(); + K3bIsoImager::init(); +} + + +void K3bVideoDvdImager::fixVideoDVDSettings() +{ + // Video DVD defaults, we cannot set these in K3bVideoDvdDoc since they + // will be overwritten in the burn dialog unless we create some K3bVideoDVDIsoOptions + // class with different defaults. But since the whole Video DVD project is a hack we + // go the easy road. + K3bIsoOptions o = d->doc->isoOptions(); + o.setISOLevel(1); + o.setISOallow31charFilenames(false); + o.setCreateJoliet(false); + o.setJolietLong(false); + o.setCreateRockRidge(false); + o.setCreateUdf(true); + d->doc->setIsoOptions( o ); +} + + +void K3bVideoDvdImager::calculateSize() +{ + fixVideoDVDSettings(); + K3bIsoImager::calculateSize(); +} + + +int K3bVideoDvdImager::writePathSpec() +{ + // + // Create a temp dir and link all contents of the VIDEO_TS dir to make mkisofs + // able to handle the VideoDVD stuff. + // + // mkisofs is not able to create VideoDVDs from graft-points. + // + // We do this here since K3bIsoImager::start calls cleanup which deletes the temp files + // + QDir dir( KGlobal::dirs()->resourceDirs( "tmp" ).first() ); + d->tempPath = K3b::findUniqueFilePrefix( "k3bVideoDvd", dir.path() ); + kdDebug() << "(K3bVideoDvdImager) creating temp dir: " << d->tempPath << endl; + if( !dir.mkdir( d->tempPath, true ) ) { + emit infoMessage( i18n("Unable to create temporary directory '%1'.").arg(d->tempPath), ERROR ); + return -1; + } + + dir.cd( d->tempPath ); + if( !dir.mkdir( "VIDEO_TS" ) ) { + emit infoMessage( i18n("Unable to create temporary directory '%1'.").arg(d->tempPath + "/VIDEO_TS"), ERROR ); + return -1; + } + + for( QPtrListIterator it( d->doc->videoTsDir()->children() ); *it; ++it ) { + if( (*it)->isDir() ) { + emit infoMessage( i18n("Found invalid entry in the VIDEO_TS folder (%1).").arg((*it)->k3bName()), ERROR ); + return -1; + } + + // convert to upper case names + if( ::symlink( QFile::encodeName( (*it)->localPath() ), + QFile::encodeName( d->tempPath + "/VIDEO_TS/" + (*it)->k3bName().upper() ) ) == -1 ) { + emit infoMessage( i18n("Unable to link temporary file in folder %1.").arg( d->tempPath ), ERROR ); + return -1; + } + } + + + return K3bIsoImager::writePathSpec(); +} + + +int K3bVideoDvdImager::writePathSpecForDir( K3bDirItem* dirItem, QTextStream& stream ) +{ + // + // We handle the VIDEO_TS dir differently since otherwise mkisofs is not able to + // open the VideoDVD structures (see addMkisofsParameters) + // + if( dirItem == d->doc->videoTsDir() ) { + return 0; + } + + int num = 0; + for( QPtrListIterator it( dirItem->children() ); it.current(); ++it ) { + K3bDataItem* item = it.current(); + num++; + + if( item->isDir() ) { + // we cannot add the video_ts dir twice + if( item != d->doc->videoTsDir() ) { + stream << escapeGraftPoint( item->writtenPath() ) + << "=" + << escapeGraftPoint( dummyDir( static_cast(item) ) ) << "\n"; + } + + int x = writePathSpecForDir( dynamic_cast(item), stream ); + if( x >= 0 ) + num += x; + else + return -1; + } + else { + writePathSpecForFile( static_cast(item), stream ); + } + } + + return num; +} + + +bool K3bVideoDvdImager::addMkisofsParameters( bool printSize ) +{ + // Here is another bad design: we assume that K3bIsoImager::start does not add additional + // parameters to the process. :( + if( K3bIsoImager::addMkisofsParameters( printSize ) ) { + *m_process << "-dvd-video"; + *m_process << "-f"; // follow symlinks + *m_process << d->tempPath; + return true; + } + else + return false; +} + + +void K3bVideoDvdImager::cleanup() +{ + if( QFile::exists( d->tempPath ) ) { + QDir dir( d->tempPath ); + dir.cd( "VIDEO_TS" ); + for( QPtrListIterator it( d->doc->videoTsDir()->children() ); *it; ++it ) + dir.remove( (*it)->k3bName().upper() ); + dir.cdUp(); + dir.rmdir( "VIDEO_TS" ); + dir.cdUp(); + dir.rmdir( d->tempPath ); + } + d->tempPath = QString::null; + + K3bIsoImager::cleanup(); +} + + +void K3bVideoDvdImager::slotReceivedStderr( const QString& line ) +{ + if( line.contains( "Unable to make a DVD-Video image" ) ) { + emit infoMessage( i18n("The project does not contain all necessary VideoDVD files."), WARNING ); + emit infoMessage( i18n("The resulting DVD will most likely not be playable on a Hifi DVD player."), WARNING ); + } + else + K3bIsoImager::slotReceivedStderr( line ); +} + +#include "k3bvideodvdimager.moc" diff --git a/libk3b/projects/videodvd/k3bvideodvdimager.h b/libk3b/projects/videodvd/k3bvideodvdimager.h new file mode 100644 index 0000000..0062d55 --- /dev/null +++ b/libk3b/projects/videodvd/k3bvideodvdimager.h @@ -0,0 +1,61 @@ +/* + * + * $Id: k3bvideodvdimager.h 633751 2007-02-15 08:22:49Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_VIDEODVD_IMAGER_H_ +#define _K3B_VIDEODVD_IMAGER_H_ + + +#include + +class K3bVideoDvdDoc; + + +/** + * Create VideoDVD images with mkisofs. The difference + * to the IsoImager is the -dvd-video option and the fact + * that all VIDEO_TS files need to be in one local folder since + * otherwise mkisofs is not able to find the dvd structures. + */ +class K3bVideoDvdImager : public K3bIsoImager +{ + Q_OBJECT + + public: + K3bVideoDvdImager( K3bVideoDvdDoc* doc, K3bJobHandler*, QObject* parent = 0, const char* name = 0 ); + virtual ~K3bVideoDvdImager(); + + public slots: + virtual void start(); + virtual void init(); + virtual void calculateSize(); + + protected: + bool addMkisofsParameters( bool printSize = false ); + int writePathSpec(); + void cleanup(); + int writePathSpecForDir( K3bDirItem* dirItem, QTextStream& stream ); + + protected slots: + virtual void slotReceivedStderr( const QString& ); + + private: + void fixVideoDVDSettings(); + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/projects/videodvd/k3bvideodvdjob.cpp b/libk3b/projects/videodvd/k3bvideodvdjob.cpp new file mode 100644 index 0000000..f4e6129 --- /dev/null +++ b/libk3b/projects/videodvd/k3bvideodvdjob.cpp @@ -0,0 +1,101 @@ +/* + * + * $Id: k3bvideodvdjob.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bvideodvdjob.h" +#include "k3bvideodvddoc.h" +#include "k3bvideodvdimager.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + + + +K3bVideoDvdJob::K3bVideoDvdJob( K3bVideoDvdDoc* doc, K3bJobHandler* jh, QObject* parent ) + : K3bDvdJob( doc, jh, parent ), + m_doc(doc) +{ +} + + +K3bVideoDvdJob::~K3bVideoDvdJob() +{ +} + + +void K3bVideoDvdJob::prepareImager() +{ + setImager( new K3bVideoDvdImager( m_doc, this ) ); +} + + +bool K3bVideoDvdJob::prepareWriterJob() +{ + K3bGrowisofsWriter* writer = new K3bGrowisofsWriter( m_doc->burner(), this, this ); + + // these do only make sense with DVD-R(W) + writer->setSimulate( m_doc->dummy() ); + writer->setBurnSpeed( m_doc->speed() ); + + // DAO seems to be the better default for Video DVD... !? + if( m_doc->writingMode() == K3b::DAO || m_doc->writingMode() == K3b::WRITING_MODE_AUTO ) + writer->setWritingMode( K3b::DAO ); + + writer->setMultiSession( false ); + writer->setCloseDvd( true ); + + if( m_doc->onTheFly() ) { + writer->setImageToWrite( QString::null ); // read from stdin + writer->setTrackSize( m_isoImager->size() ); + } + else + writer->setImageToWrite( m_doc->tempDir() ); + + setWriterJob( writer ); + + return true; +} + + +QString K3bVideoDvdJob::jobDescription() const +{ + if( m_doc->onlyCreateImages() ) { + return i18n("Creating Video DVD Image File"); + } + else { + return i18n("Writing Video DVD") + + ( m_doc->isoOptions().volumeID().isEmpty() + ? QString::null + : QString( " (%1)" ).arg(m_doc->isoOptions().volumeID()) ); + } +} + + +QString K3bVideoDvdJob::jobDetails() const +{ + return ( i18n("ISO9660/Udf Filesystem (Size: %1)").arg(KIO::convertSize( doc()->size() )) + + ( m_doc->copies() > 1 + ? i18n(" - %n copy", " - %n copies", m_doc->copies()) + : QString::null ) ); +} + +#include "k3bvideodvdjob.moc" diff --git a/libk3b/projects/videodvd/k3bvideodvdjob.h b/libk3b/projects/videodvd/k3bvideodvdjob.h new file mode 100644 index 0000000..3f03cea --- /dev/null +++ b/libk3b/projects/videodvd/k3bvideodvdjob.h @@ -0,0 +1,46 @@ +/* + * + * $Id: k3bvideodvdjob.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_VIDEO_DVD_JOB_H_ +#define _K3B_VIDEO_DVD_JOB_H_ + +#include + + +class K3bVideoDvdDoc; + +/** + * This class heavily depends on K3bDvdJob and uses some of it's internals. + */ +class K3bVideoDvdJob : public K3bDvdJob +{ + Q_OBJECT + + public: + K3bVideoDvdJob( K3bVideoDvdDoc*, K3bJobHandler*, QObject* parent = 0 ); + virtual ~K3bVideoDvdJob(); + + virtual QString jobDescription() const; + virtual QString jobDetails() const; + + private: + bool prepareWriterJob(); + void prepareImager(); + + K3bVideoDvdDoc* m_doc; +}; + +#endif diff --git a/libk3b/scripts/Makefile.am b/libk3b/scripts/Makefile.am new file mode 100644 index 0000000..6318b9b --- /dev/null +++ b/libk3b/scripts/Makefile.am @@ -0,0 +1,11 @@ +bin_SCRIPTS = k3b_automount + +# k3b_automount needs to be installed setuid root +install-exec-hook: + @(chown 0 $(DESTDIR)$(bindir)/k3b_automount && chmod 4755 $(DESTDIR)$(bindir)/k3b_automount) || echo "Please make k3b_automount setuid root" >&2 + @echo "" + @echo "k3b_automount is by default installed with a set SETUID root bit!" + @echo "This is needed for K3b to be able to temporarily disable automounting via" + @echo "subfs or supermount while burning." + @echo "" + diff --git a/libk3b/scripts/k3b_automount b/libk3b/scripts/k3b_automount new file mode 100755 index 0000000..e86e960 --- /dev/null +++ b/libk3b/scripts/k3b_automount @@ -0,0 +1,66 @@ +#!/bin/bash + +# +# This script is able to disable and enable automounting for a device. +# It's usage is as follows: +# +# k3b_automount disable /dev/cdrom +# or +# k3b_automount enable /dev/cdrom +# +# /dev/cdrom needs to have an entry in /etc/fstab. +# +# The supported automounting systems are subfs and supermount. +# +# Exit codes: +# 0 - success +# 1 - wrong usage +# 2 - device not configured with subfs/supermount in /etc/fstab +# X - failed to mount/umount +# + +DISABLE=1 + +if [ $1 = "disable" ]; then + DISABLE=1 +elif [ $1 = "enable" ]; then + DISABLE=0 +else + echo "Usage: $0 disable|enable " + exit 1 +fi + +DEVICE=$2 + +if [ -z $DEVICE ]; then + echo "Usage: $0 disable|enable " + exit 1 +fi + +# we have a mode and a device + +# open the fstab file and search the DEVICE +if [ -n "`grep $DEVICE /etc/fstab | grep "subfs\|supermount"`" ]; then + if [ $DISABLE = 1 ]; then + umount $DEVICE + else + mount $DEVICE + fi + exit $? +fi + +# +# Ok, not using subfs or supermount +# If some other userspace automounter (like ivman) is running it is sufficient +# to unmount the device now to get the burning started. This however does not +# fix the problem with DVD+RW burning which may be mounted once the burning has +# been started. +# +# So we unmount the device in case it is mounted with iso9660 or udf (just to add +# some security to this suid script. :( +# +if [ $DISABLE = 1 ] && [ -n "`grep $DEVICE /etc/mtab | grep "iso9660\|udf"`" ]; then + umount $DEVICE + exit $? +fi +exit 2 diff --git a/libk3b/tools/Makefile.am b/libk3b/tools/Makefile.am new file mode 100644 index 0000000..d48a295 --- /dev/null +++ b/libk3b/tools/Makefile.am @@ -0,0 +1,44 @@ +AM_CPPFLAGS= -I$(srcdir)/../../src \ + -I$(srcdir)/../core \ + -I$(srcdir)/../../libk3bdevice \ + -I$(srcdir)/.. \ + $(all_includes) + +noinst_LTLIBRARIES = libk3btools.la + +libk3btools_la_LIBADD = libisofs/libisofs.la + +libk3btools_la_LDFLAGS = $(all_libraries) + +libk3btools_la_SOURCES = k3bwavefilewriter.cpp k3bbusywidget.cpp k3bdeviceselectiondialog.cpp \ + k3bmd5job.cpp k3btitlelabel.cpp k3bcutcombobox.cpp \ + k3bstringutils.cpp k3bdevicecombobox.cpp kcutlabel.cpp \ + k3bstdguiitems.cpp k3bvalidators.cpp k3bthroughputestimator.cpp \ + k3biso9660.cpp k3bmultichoicedialog.cpp k3bdevicehandler.cpp \ + k3bcdparanoialib.cpp k3blistview.cpp k3bmsfedit.cpp \ + k3bcdtextvalidator.cpp k3bintvalidator.cpp k3bexceptions.cpp \ + k3bprogressdialog.cpp k3btoolbox.cpp k3bpushbutton.cpp \ + k3blistviewitemanimator.cpp k3bthreadwidget.cpp k3bradioaction.cpp \ + k3bsignalwaiter.cpp k3blibdvdcss.cpp k3biso9660backend.cpp \ + k3bpipe.cpp k3bchecksumpipe.cpp k3btoolbutton.cpp \ + k3bintmapcombobox.cpp k3bdirsizejob.cpp k3brichtextlabel.cpp \ + k3btempfile.cpp k3bactivepipe.cpp k3bfilesplitter.cpp \ + k3bfilesysteminfo.cpp + +include_HEADERS = k3bwavefilewriter.h k3bbusywidget.h k3bdeviceselectiondialog.h \ + k3bmd5job.h k3bcutcombobox.h k3bstringutils.h \ + k3bdevicecombobox.h kcutlabel.h k3bstdguiitems.h \ + k3bvalidators.h k3bthroughputestimator.h k3biso9660.h \ + k3bmultichoicedialog.h k3bdevicehandler.h k3bcdparanoialib.h \ + k3blistview.h k3bmsfedit.h k3bcdtextvalidator.h \ + k3bintvalidator.h k3bexceptions.h k3bprogressdialog.h \ + k3btoolbox.h k3bpushbutton.h k3blistviewitemanimator.h \ + k3bthreadwidget.h k3bradioaction.h k3bsignalwaiter.h \ + k3biso9660backend.h k3bpipe.h k3bdirsizejob.h \ + k3bchecksumpipe.h k3btoolbutton.h k3bintmapcombobox.h \ + k3brichtextlabel.h k3btempfile.h k3bactivepipe.h \ + k3bfilesplitter.h k3bfilesysteminfo.h + +METASOURCES = AUTO + +SUBDIRS = libisofs diff --git a/libk3b/tools/k3bactivepipe.cpp b/libk3b/tools/k3bactivepipe.cpp new file mode 100644 index 0000000..5a1e575 --- /dev/null +++ b/libk3b/tools/k3bactivepipe.cpp @@ -0,0 +1,255 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bactivepipe.h" + +#include + +#include + +#include +#include + +#include + + +class K3bActivePipe::Private : public QThread +{ +public: + Private( K3bActivePipe* pipe ) : + m_pipe( pipe ), + fdToReadFrom(-1), + fdToWriteTo(-1), + sourceIODevice(0), + sinkIODevice(0), + closeFdToReadFrom(false), + closeFdToWriteTo(false) { + } + + void run() { + kdDebug() << "(K3bActivePipe) started thread." << endl; + bytesRead = bytesWritten = 0; + buffer.resize( 10*2048 ); + ssize_t r = 0; + while( ( r = m_pipe->read( buffer.data(), buffer.size() ) ) > 0 ) { + + bytesRead += r; + + // write it out + ssize_t w = 0; + ssize_t ww = 0; + while( w < r ) { + if( ( ww = m_pipe->write( buffer.data()+w, r-w ) ) > 0 ) { + w += ww; + bytesWritten += ww; + } + else { + kdDebug() << "(K3bActivePipe) write failed." << endl; + close( closeWhenDone ); + return; + } + } + } + // kdDebug() << "(K3bActivePipe) thread done: " << r << " (total bytes read/written: " << bytesRead << "/" << bytesWritten << ")" << endl; + close( closeWhenDone ); + } + + int readFd() const { + if( fdToReadFrom == -1 ) + return pipeIn.out(); + else + return fdToReadFrom; + } + + int writeFd() const { + if( fdToWriteTo == -1 ) + return pipeOut.in(); + else + return fdToWriteTo; + } + + void close( bool closeAll ) { + if( sourceIODevice ) + sourceIODevice->close(); + if( sinkIODevice ) + sinkIODevice->close(); + + if( closeAll ) { + pipeIn.close(); + pipeOut.close(); + if( fdToWriteTo != -1 && + closeFdToWriteTo ) + ::close( fdToWriteTo ); + + if( fdToReadFrom != -1 && + closeFdToReadFrom ) + ::close( fdToReadFrom ); + } + } + +private: + K3bActivePipe* m_pipe; + +public: + int fdToReadFrom; + int fdToWriteTo; + K3bPipe pipeIn; + K3bPipe pipeOut; + + QIODevice* sourceIODevice; + QIODevice* sinkIODevice; + + bool closeWhenDone; + bool closeFdToReadFrom; + bool closeFdToWriteTo; + + QByteArray buffer; + + Q_UINT64 bytesRead; + Q_UINT64 bytesWritten; +}; + + +K3bActivePipe::K3bActivePipe() +{ + d = new Private( this ); +} + + +K3bActivePipe::~K3bActivePipe() +{ + delete d; +} + + +bool K3bActivePipe::open( bool closeWhenDone ) +{ + if( d->running() ) + return false; + + d->closeWhenDone = closeWhenDone; + + if( d->sourceIODevice ) { + if( !d->sourceIODevice->open( IO_ReadOnly ) ) + return false; + } + else if( d->fdToReadFrom == -1 && !d->pipeIn.open() ) { + return false; + } + + if( d->sinkIODevice ) { + if( !d->sinkIODevice->open( IO_WriteOnly ) ) + return false; + } + else if( d->fdToWriteTo == -1 && !d->pipeOut.open() ) { + close(); + return false; + } + + kdDebug() << "(K3bActivePipe) successfully opened pipe." << endl; + + d->start(); + return true; +} + + +void K3bActivePipe::close() +{ + d->pipeIn.closeIn(); + d->wait(); + d->close( true ); +} + + +void K3bActivePipe::readFromFd( int fd, bool close ) +{ + d->fdToReadFrom = fd; + d->sourceIODevice = 0; + d->closeFdToReadFrom = close; +} + + +void K3bActivePipe::writeToFd( int fd, bool close ) +{ + d->fdToWriteTo = fd; + d->sinkIODevice = 0; + d->closeFdToWriteTo = close; +} + + +void K3bActivePipe::readFromIODevice( QIODevice* dev ) +{ + d->fdToReadFrom = -1; + d->sourceIODevice = dev; +} + + +void K3bActivePipe::writeToIODevice( QIODevice* dev ) +{ + d->fdToWriteTo = -1; + d->sinkIODevice = dev; +} + + +int K3bActivePipe::in() const +{ + return d->pipeIn.in(); +} + + +int K3bActivePipe::out() const +{ + return d->pipeOut.out(); +} + + +int K3bActivePipe::read( char* data, int max ) +{ + if( d->sourceIODevice ) + return d->sourceIODevice->readBlock( data, max ); + else + return ::read( d->readFd(), data, max ); +} + + +int K3bActivePipe::write( char* data, int max ) +{ + if( d->sinkIODevice ) + return d->sinkIODevice->writeBlock( data, max ); + else + return ::write( d->writeFd(), data, max ); +} + + +bool K3bActivePipe::pumpSync() +{ + if( open( true ) ) + d->wait(); + else + return false; + return true; +} + + +Q_UINT64 K3bActivePipe::bytesRead() const +{ + return d->bytesRead; +} + + +Q_UINT64 K3bActivePipe::bytesWritten() const +{ + return d->bytesWritten; +} diff --git a/libk3b/tools/k3bactivepipe.h b/libk3b/tools/k3bactivepipe.h new file mode 100644 index 0000000..367646d --- /dev/null +++ b/libk3b/tools/k3bactivepipe.h @@ -0,0 +1,134 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_ACTIVE_PIPE_H_ +#define _K3B_ACTIVE_PIPE_H_ + +#include + +#include + + +class QIODevice; + + +/** + * The active pipe pumps data from a source to a sink using an + * additional thread. + */ +class LIBK3B_EXPORT K3bActivePipe +{ + public: + K3bActivePipe(); + virtual ~K3bActivePipe(); + + /** + * Opens the pipe and thus starts the + * pumping. + * + * \param closeWhenDone If true the pipes will be closed + * once all data has been read. + */ + virtual bool open( bool closeWhenDone = false ); + + /** + * Opens the pipe syncroneously and blocks until all data has been + * pumped through. + * The pipe is closed afterwards. + */ + bool pumpSync(); + + /** + * Close the pipe + */ + virtual void close(); + + /** + * Set the file descriptor to read from. If this is -1 (the default) then + * data has to be piped into the in() file descriptor. + * + * \param fd The file descriptor to read from. + * \param close If true the reading file descriptor will be closed on a call to close() + */ + void readFromFd( int fd, bool close = false ); + + /** + * Set the file descriptor to write to. If this is -1 (the default) then + * data has to read from the out() file descriptor. + * + * \param fd The file descriptor to write to. + * \param close If true the reading file descriptor will be closed on a call to close() + */ + void writeToFd( int fd, bool close = false ); + + /** + * Read from a QIODevice instead of a file descriptor. + * The device will be opened IO_ReadOnly and closed + * afterwards. + */ + void readFromIODevice( QIODevice* dev ); + + /** + * Write to a QIODevice instead of a file descriptor. + * The device will be opened IO_WriteOnly and closed + * afterwards. + */ + void writeToIODevice( QIODevice* dev ); + + /** + * The file descriptor to write into + * Only valid if no source has been set + */ + int in() const; + + /** + * The file descriptor to read from + * Only valid if no sink has been set + */ + int out() const; + + /** + * The number of bytes that have been read. + */ + Q_UINT64 bytesRead() const; + + /** + * The number of bytes that have been written. + */ + Q_UINT64 bytesWritten() const; + + protected: + /** + * Reads the data from the source. + * The default implementation reads from the file desc + * set via readFromFd or from in() + */ + virtual int read( char* data, int max ); + + /** + * Write the data to the sink. + * The default implementation writes to the file desc + * set via writeToFd or out() + * + * Can be reimplememented to further process the data. + */ + virtual int write( char* data, int max ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bbusywidget.cpp b/libk3b/tools/k3bbusywidget.cpp new file mode 100644 index 0000000..d222107 --- /dev/null +++ b/libk3b/tools/k3bbusywidget.cpp @@ -0,0 +1,103 @@ +/* + * + * $Id: k3bbusywidget.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bbusywidget.h" + +#include +#include + +#include + + +K3bBusyWidget::K3bBusyWidget( QWidget* parent, const char* name ) + : QFrame( parent, name ) +{ + m_busyTimer = new QTimer( this ); + m_iBusyPosition = 0; + + connect( m_busyTimer, SIGNAL(timeout()), this, SLOT(animateBusy()) ); + + m_bBusy = false; +} + +K3bBusyWidget::~K3bBusyWidget() +{ +} + + +void K3bBusyWidget::showBusy( bool b ) +{ + m_bBusy = b; + +// if( b ) { +// m_iBusyCounter++; +// } +// else if( m_iBusyCounter > 0 ) { +// m_iBusyCounter--; +// } + + if( m_bBusy ) { + if( !m_busyTimer->isActive() ) + m_busyTimer->start( 500 ); + } + else { + if( m_busyTimer->isActive() ) + m_busyTimer->stop(); + update(); + m_iBusyPosition = 0; + } +} + + +void K3bBusyWidget::animateBusy() +{ + m_iBusyPosition++; + update(); +} + + +QSize K3bBusyWidget::sizeHint() const +{ + return minimumSizeHint(); +} + + +QSize K3bBusyWidget::minimumSizeHint() const +{ + return QSize( 2*frameWidth() + 62, 10 ); +} + + +void K3bBusyWidget::drawContents( QPainter* p ) +{ + QRect rect = contentsRect(); + + int squareSize = 8; + + int pos = 2 + m_iBusyPosition * (squareSize + 2); + + // check if the position is in the visible area + if( pos + 8 + 2> rect.width() ) { + m_iBusyPosition = 0; + pos = 2; + } + + // p->eraseRect( rect ); + if( m_bBusy ) + p->fillRect( pos, (rect.height() - squareSize)/2, squareSize, squareSize, KGlobalSettings::highlightColor() ); +} + + +#include "k3bbusywidget.moc" diff --git a/libk3b/tools/k3bbusywidget.h b/libk3b/tools/k3bbusywidget.h new file mode 100644 index 0000000..2a6934c --- /dev/null +++ b/libk3b/tools/k3bbusywidget.h @@ -0,0 +1,54 @@ +/* + * + * $Id: k3bbusywidget.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_BUSY_WIDGET_H +#define K3B_BUSY_WIDGET_H + + +#include +#include "k3b_export.h" + +class QPainter; +class QTimer; + + +class LIBK3B_EXPORT K3bBusyWidget : public QFrame +{ + Q_OBJECT + + public: + K3bBusyWidget( QWidget* parent = 0, const char* name = 0 ); + ~K3bBusyWidget(); + + void showBusy( bool b ); + + QSize sizeHint() const; + QSize minimumSizeHint() const; + + protected: + void drawContents( QPainter* p ); + + private slots: + void animateBusy(); + + private: + bool m_bBusy; + int m_iBusyPosition; + + QTimer* m_busyTimer; +}; + + +#endif diff --git a/libk3b/tools/k3bcdparanoialib.cpp b/libk3b/tools/k3bcdparanoialib.cpp new file mode 100644 index 0000000..5976941 --- /dev/null +++ b/libk3b/tools/k3bcdparanoialib.cpp @@ -0,0 +1,783 @@ +/* + * + * $Id: k3bcdparanoialib.cpp 621693 2007-01-09 14:38:25Z trueg $ + * Copyright (C) 2003-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include + +#include "k3bcdparanoialib.h" + +#include +#include +#include + +#include + +#include + +#include +#include + + +static bool s_haveLibCdio = false; + + +void* K3bCdparanoiaLib::s_libInterface = 0; +void* K3bCdparanoiaLib::s_libParanoia = 0; +int K3bCdparanoiaLib::s_counter = 0; + + +#define CDDA_IDENTIFY s_haveLibCdio ? "cdio_cddap_identify" : "cdda_identify" +#define CDDA_CLOSE s_haveLibCdio ? "cdio_cddap_close" : "cdda_close" +#define CDDA_OPEN s_haveLibCdio ? "cdio_cddap_open" : "cdda_open" +#define CDDA_TRACK_FIRSTSECTOR s_haveLibCdio ? "cdio_cddap_track_firstsector" : "cdda_track_firstsector" +#define CDDA_TRACK_LASTSECTOR s_haveLibCdio ? "cdio_cddap_track_lastsector" : "cdda_track_lastsector" +#define CDDA_VERBOSE_SET s_haveLibCdio ? "cdio_cddap_verbose_set" : "cdda_verbose_set" +#define CDDA_DISC_FIRSTSECTOR s_haveLibCdio ? "cdio_cddap_disc_firstsector" : "cdda_disc_firstsector" + +#define PARANOIA_INIT s_haveLibCdio ? "cdio_paranoia_init" : "paranoia_init" +#define PARANOIA_FREE s_haveLibCdio ? "cdio_paranoia_free" : "paranoia_free" +#define PARANOIA_MODESET s_haveLibCdio ? "cdio_paranoia_modeset" : "paranoia_modeset" +#define PARANOIA_SEEK s_haveLibCdio ? "cdio_paranoia_seek" : "paranoia_seek" +#define PARANOIA_READ_LIMITED s_haveLibCdio ? "cdio_paranoia_read_limited" : "paranoia_read_limited" + + +// from cdda_paranoia.h +#define PARANOIA_CB_READ 0 +#define PARANOIA_CB_VERIFY 1 +#define PARANOIA_CB_FIXUP_EDGE 2 +#define PARANOIA_CB_FIXUP_ATOM 3 +#define PARANOIA_CB_SCRATCH 4 +#define PARANOIA_CB_REPAIR 5 +#define PARANOIA_CB_SKIP 6 +#define PARANOIA_CB_DRIFT 7 +#define PARANOIA_CB_BACKOFF 8 +#define PARANOIA_CB_OVERLAP 9 +#define PARANOIA_CB_FIXUP_DROPPED 10 +#define PARANOIA_CB_FIXUP_DUPED 11 +#define PARANOIA_CB_READERR 12 + + + +static void paranoiaCallback( long, int status ) +{ + // do nothing so far.... + return; + + switch( status ) { + case -1: + break; + case -2: + break; + case PARANOIA_CB_READ: + // no problem + // does only this mean that the sector has been read? +// m_lastReadSector = sector; // this seems to be rather useless +// m_readSectors++; + break; + case PARANOIA_CB_VERIFY: + break; + case PARANOIA_CB_FIXUP_EDGE: + break; + case PARANOIA_CB_FIXUP_ATOM: + break; + case PARANOIA_CB_SCRATCH: + // scratch detected + break; + case PARANOIA_CB_REPAIR: + break; + case PARANOIA_CB_SKIP: + // skipped sector + break; + case PARANOIA_CB_DRIFT: + break; + case PARANOIA_CB_BACKOFF: + break; + case PARANOIA_CB_OVERLAP: + // sector does not seem to contain the current + // sector but the amount of overlapped data + // m_overlap = sector; + break; + case PARANOIA_CB_FIXUP_DROPPED: + break; + case PARANOIA_CB_FIXUP_DUPED: + break; + case PARANOIA_CB_READERR: + break; + } +} + + + +extern "C" { + struct cdrom_drive; + struct cdrom_paranoia; + + // HINT: these pointers must NOT have the same name like the actual methods! + // I added "cdda_" as prefix + // Before doing that K3b crashed in cdda_open! + // Can anyone please explain that to me? + + // cdda_interface + cdrom_drive* (*cdda_cdda_identify)(const char*, int, char**); + int (*cdda_cdda_open)(cdrom_drive *d); + int (*cdda_cdda_close)(cdrom_drive *d); + long (*cdda_cdda_track_firstsector)( cdrom_drive*, int ); + long (*cdda_cdda_track_lastsector)( cdrom_drive*, int ); + long (*cdda_cdda_disc_firstsector)(cdrom_drive *d); + void (*cdda_cdda_verbose_set)(cdrom_drive *d,int err_action, int mes_action); + + // cdda_paranoia + cdrom_paranoia* (*cdda_paranoia_init)(cdrom_drive*); + void (*cdda_paranoia_free)(cdrom_paranoia *p); + void (*cdda_paranoia_modeset)(cdrom_paranoia *p, int mode); + int16_t* (*cdda_paranoia_read_limited)(cdrom_paranoia *p, void(*callback)(long,int), int); + long (*cdda_paranoia_seek)(cdrom_paranoia *p,long seek,int mode); +} + +// from cdda_paranoia.h +#define PARANOIA_MODE_FULL 0xff +#define PARANOIA_MODE_DISABLE 0 + +#define PARANOIA_MODE_VERIFY 1 +#define PARANOIA_MODE_FRAGMENT 2 +#define PARANOIA_MODE_OVERLAP 4 +#define PARANOIA_MODE_SCRATCH 8 +#define PARANOIA_MODE_REPAIR 16 +#define PARANOIA_MODE_NEVERSKIP 32 + + + +/** + * Internal class used by K3bCdparanoiaLib + */ +class K3bCdparanoiaLibData +{ + public: + K3bCdparanoiaLibData( K3bDevice::Device* dev ) + : m_device(dev), + m_drive(0), + m_paranoia(0), + m_currentSector(0) { + s_dataMap.insert( dev, this ); + } + + ~K3bCdparanoiaLibData() { + paranoiaFree(); + + s_dataMap.erase( m_device ); + } + + K3bDevice::Device* device() const { return m_device; } + void paranoiaModeSet( int ); + bool paranoiaInit(); + void paranoiaFree(); + int16_t* paranoiaRead( void(*callback)(long,int), int maxRetries ); + long paranoiaSeek( long, int ); + long firstSector( int ); + long lastSector( int ); + long sector() const { return m_currentSector; } + + static K3bCdparanoiaLibData* data( K3bDevice::Device* dev ) { + QMap::const_iterator it = s_dataMap.find( dev ); + if( it == s_dataMap.constEnd() ) + return new K3bCdparanoiaLibData( dev ); + else + return *it; + } + + static void freeAll() { + // clean up all K3bCdparanoiaLibData instances + for( QMap::iterator it = s_dataMap.begin(); + it != s_dataMap.end(); ++it ) + delete it.data(); + } + + private: + // + // We have exactly one instance of K3bCdparanoiaLibData per device + // + static QMap s_dataMap; + + K3bDevice::Device* m_device; + + cdrom_drive* m_drive; + cdrom_paranoia* m_paranoia; + + long m_currentSector; + + QMutex mutex; +}; + + +QMap K3bCdparanoiaLibData::s_dataMap; + +bool K3bCdparanoiaLibData::paranoiaInit() +{ + mutex.lock(); + + if( m_drive ) + paranoiaFree(); + + // since we use cdparanoia to open the device it is important to close + // the device here + m_device->close(); + + m_drive = cdda_cdda_identify( QFile::encodeName(m_device->blockDeviceName()), 0, 0 ); + if( m_drive == 0 ) { + mutex.unlock(); + return false; + } + + // cdda_cdda_verbose_set( m_drive, 1, 1 ); + + cdda_cdda_open( m_drive ); + m_paranoia = cdda_paranoia_init( m_drive ); + if( m_paranoia == 0 ) { + mutex.unlock(); + paranoiaFree(); + return false; + } + + m_currentSector = 0; + + mutex.unlock(); + + return true; +} + + +void K3bCdparanoiaLibData::paranoiaFree() +{ + mutex.lock(); + + if( m_paranoia ) { + cdda_paranoia_free( m_paranoia ); + m_paranoia = 0; + } + if( m_drive ) { + cdda_cdda_close( m_drive ); + m_drive = 0; + } + + mutex.unlock(); +} + + +void K3bCdparanoiaLibData::paranoiaModeSet( int mode ) +{ + mutex.lock(); + cdda_paranoia_modeset( m_paranoia, mode ); + mutex.unlock(); +} + + +int16_t* K3bCdparanoiaLibData::paranoiaRead( void(*callback)(long,int), int maxRetries ) +{ + if( m_paranoia ) { + mutex.lock(); + int16_t* data = cdda_paranoia_read_limited( m_paranoia, callback, maxRetries ); + if( data ) + m_currentSector++; + mutex.unlock(); + return data; + } + else + return 0; +} + + +long K3bCdparanoiaLibData::firstSector( int track ) +{ + if( m_drive ) { + mutex.lock(); + long sector = cdda_cdda_track_firstsector( m_drive, track ); + mutex.unlock(); + return sector; + } + else + return -1; +} + +long K3bCdparanoiaLibData::lastSector( int track ) +{ + if( m_drive ) { + mutex.lock(); + long sector = cdda_cdda_track_lastsector(m_drive, track ); + mutex.unlock(); + return sector; + } + else + return -1; +} + + +long K3bCdparanoiaLibData::paranoiaSeek( long sector, int mode ) +{ + if( m_paranoia ) { + mutex.lock(); + m_currentSector = cdda_paranoia_seek( m_paranoia, sector, mode ); + mutex.unlock(); + return m_currentSector; + } + else + return -1; +} + + + +class K3bCdparanoiaLib::Private +{ +public: + Private() + : device(0), + currentSector(0), + startSector(0), + lastSector(0), + status(S_OK), + paranoiaLevel(0), + neverSkip(true), + maxRetries(5), + data(0) { + } + + ~Private() { + } + + void updateParanoiaMode() { + // from cdrdao 1.1.7 + int paranoiaMode = PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP; + + switch( paranoiaLevel ) { + case 0: + paranoiaMode = PARANOIA_MODE_DISABLE; + break; + + case 1: + paranoiaMode |= PARANOIA_MODE_OVERLAP; + paranoiaMode &= ~PARANOIA_MODE_VERIFY; + break; + + case 2: + paranoiaMode &= ~(PARANOIA_MODE_SCRATCH|PARANOIA_MODE_REPAIR); + break; + } + + if( neverSkip ) + paranoiaMode |= PARANOIA_MODE_NEVERSKIP; + + data->paranoiaModeSet( paranoiaMode ); + } + + // high-level api + K3bDevice::Device* device; + K3bDevice::Toc toc; + long currentSector; + long startSector; + long lastSector; + int status; + unsigned int currentTrack; + int paranoiaLevel; + bool neverSkip; + int maxRetries; + + K3bCdparanoiaLibData* data; +}; + + +K3bCdparanoiaLib::K3bCdparanoiaLib() +{ + d = new Private(); + s_counter++; +} + + +K3bCdparanoiaLib::~K3bCdparanoiaLib() +{ + delete d; + s_counter--; + if( s_counter == 0 ) { + K3bCdparanoiaLibData::freeAll(); + + // cleanup the dynamically loaded lib + dlclose( s_libInterface ); + dlclose( s_libParanoia ); + s_libInterface = 0; + s_libParanoia = 0; + } +} + + +bool K3bCdparanoiaLib::load() +{ + cdda_cdda_identify = (cdrom_drive* (*) (const char*, int, char**))dlsym( s_libInterface, CDDA_IDENTIFY ); + cdda_cdda_open = (int (*) (cdrom_drive*))dlsym( s_libInterface, CDDA_OPEN ); + cdda_cdda_close = (int (*) (cdrom_drive*))dlsym( s_libInterface, CDDA_CLOSE ); + cdda_cdda_track_firstsector = (long (*)(cdrom_drive*, int))dlsym( s_libInterface, CDDA_TRACK_FIRSTSECTOR ); + cdda_cdda_track_lastsector = (long (*)(cdrom_drive*, int))dlsym( s_libInterface, CDDA_TRACK_LASTSECTOR ); + cdda_cdda_verbose_set = (void (*)(cdrom_drive *d,int err_action, int mes_action))dlsym( s_libInterface, CDDA_VERBOSE_SET ); + cdda_cdda_disc_firstsector = (long (*)(cdrom_drive *d))dlsym( s_libInterface, CDDA_DISC_FIRSTSECTOR ); + + cdda_paranoia_init = (cdrom_paranoia* (*)(cdrom_drive*))dlsym( s_libParanoia, PARANOIA_INIT ); + cdda_paranoia_free = (void (*)(cdrom_paranoia *p))dlsym( s_libParanoia, PARANOIA_FREE ); + cdda_paranoia_modeset = (void (*)(cdrom_paranoia *p, int mode))dlsym( s_libParanoia, PARANOIA_MODESET ); + cdda_paranoia_read_limited = (int16_t* (*)(cdrom_paranoia *p, void(*callback)(long,int), int))dlsym( s_libParanoia, PARANOIA_READ_LIMITED ); + cdda_paranoia_seek = (long (*)(cdrom_paranoia *p,long seek,int mode))dlsym( s_libParanoia, PARANOIA_SEEK ); + + // check if all symbols could be resoled + if( cdda_cdda_identify == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'cdda_identify'" << endl; + return false; + } + if( cdda_cdda_open == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'cdda_open'" << endl; + return false; + } + if( cdda_cdda_close == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'cdda_close'" << endl; + return false; + } + if( cdda_cdda_track_firstsector == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'cdda_track_firstsector'" << endl; + return false; + } + if( cdda_cdda_track_lastsector == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'cdda_track_lastsector'" << endl; + return false; + } + if( cdda_cdda_disc_firstsector == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'cdda_disc_firstsector'" << endl; + return false; + } + if( cdda_cdda_verbose_set == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'cdda_verbose_set'" << endl; + return false; + } + + if( cdda_paranoia_init == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'paranoia_init'" << endl; + return false; + } + if( cdda_paranoia_free == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'paranoia_free'" << endl; + return false; + } + if( cdda_paranoia_modeset == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'paranoia_modeset'" << endl; + return false; + } + if( cdda_paranoia_read_limited == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'paranoia_read_limited'" << endl; + return false; + } + if( cdda_paranoia_seek == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve 'paranoia_seek'" << endl; + return false; + } + + return true; +} + + + +K3bCdparanoiaLib* K3bCdparanoiaLib::create() +{ + // check if libcdda_interface is avalilable + if( s_libInterface == 0 ) { + s_haveLibCdio = false; + + s_libInterface = dlopen( "libcdda_interface.so.0", RTLD_NOW|RTLD_GLOBAL ); + + // try the redhat & Co. location + if( s_libInterface == 0 ) + s_libInterface = dlopen( "cdda/libcdda_interface.so.0", RTLD_NOW|RTLD_GLOBAL ); + + // try the new cdio lib + if( s_libInterface == 0 ) { + s_libInterface = dlopen( "libcdio_cdda.so", RTLD_NOW|RTLD_GLOBAL ); + s_haveLibCdio = true; + } + + if( s_libInterface == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error while loading libcdda_interface. " << endl; + return 0; + } + + + s_libParanoia = dlopen( "libcdda_paranoia.so.0", RTLD_NOW ); + + // try the redhat & Co. location + if( s_libParanoia == 0 ) + s_libParanoia = dlopen( "cdda/libcdda_paranoia.so.0", RTLD_NOW ); + + // try the new cdio lib + if( s_haveLibCdio && s_libParanoia == 0 ) + s_libParanoia = dlopen( "libcdio_paranoia.so.0", RTLD_NOW ); + + if( s_libParanoia == 0 ) { + kdDebug() << "(K3bCdparanoiaLib) Error while loading libcdda_paranoia. " << endl; + dlclose( s_libInterface ); + s_libInterface = 0; + return 0; + } + } + + K3bCdparanoiaLib* lib = new K3bCdparanoiaLib(); + if( !lib->load() ) { + kdDebug() << "(K3bCdparanoiaLib) Error: could not resolve all symbols!" << endl; + delete lib; + return 0; + } + return lib; +} + + +bool K3bCdparanoiaLib::initParanoia( K3bDevice::Device* dev, const K3bDevice::Toc& toc ) +{ + if( !dev ) { + kdError() << "(K3bCdparanoiaLib::initParanoia) dev = 0!" << endl; + return false; + } + + close(); + + d->device = dev; + d->toc = toc; + if( d->toc.isEmpty() ) { + kdDebug() << "(K3bCdparanoiaLib) empty toc." << endl; + cleanup(); + return false; + } + + if( d->toc.contentType() == K3bDevice::DATA ) { + kdDebug() << "(K3bCdparanoiaLib) No audio tracks found." << endl; + cleanup(); + return false; + } + + // + // Get the appropriate data instance for this device + // + d->data = K3bCdparanoiaLibData::data( dev ); + + if( d->data->paranoiaInit() ) { + d->startSector = d->currentSector = d->lastSector = 0; + + return true; + } + else { + cleanup(); + return false; + } +} + + +bool K3bCdparanoiaLib::initParanoia( K3bDevice::Device* dev ) +{ + return initParanoia( dev, dev->readToc() ); +} + + +void K3bCdparanoiaLib::close() +{ + cleanup(); +} + + +void K3bCdparanoiaLib::cleanup() +{ + if( d->data ) + d->data->paranoiaFree(); + d->device = 0; + d->currentSector = 0; +} + + +bool K3bCdparanoiaLib::initReading() +{ + if( d->device ) { + // find first audio track + K3bDevice::Toc::const_iterator trackIt = d->toc.begin(); + while( (*trackIt).type() != K3bDevice::Track::AUDIO ) { + ++trackIt; + } + + long start = (*trackIt).firstSector().lba(); + + // find last audio track + while( trackIt != d->toc.end() && (*trackIt).type() == K3bDevice::Track::AUDIO ) + ++trackIt; + --trackIt; + + long end = (*trackIt).lastSector().lba(); + + return initReading( start, end ); + } + else { + kdDebug() << "(K3bCdparanoiaLib) initReading without initParanoia." << endl; + return false; + } +} + + +bool K3bCdparanoiaLib::initReading( unsigned int track ) +{ + if( d->device ) { + if( track <= d->toc.count() ) { + const K3bDevice::Track& k3bTrack = d->toc[track-1]; + if( k3bTrack.type() == K3bDevice::Track::AUDIO ) { + return initReading( k3bTrack.firstSector().lba(), k3bTrack.lastSector().lba() ); + } + else { + kdDebug() << "(K3bCdparanoiaLib) Track " << track << " no audio track." << endl; + return false; + } + } + else { + kdDebug() << "(K3bCdparanoiaLib) Track " << track << " too high." << endl; + return false; + } + } + else { + kdDebug() << "(K3bCdparanoiaLib) initReading without initParanoia." << endl; + return false; + } +} + + +bool K3bCdparanoiaLib::initReading( long start, long end ) +{ + kdDebug() << "(K3bCdparanoiaLib) initReading( " << start << ", " << end << " )" << endl; + + if( d->device ) { + if( d->toc.firstSector().lba() <= start && + d->toc.lastSector().lba() >= end ) { + d->startSector = d->currentSector = start; + d->lastSector = end; + + // determine track number + d->currentTrack = 1; + while( d->toc[d->currentTrack-1].lastSector() < start ) + d->currentTrack++; + + // let the paranoia stuff point to the startSector + d->data->paranoiaSeek( start, SEEK_SET ); + return true; + } + else { + kdDebug() << "(K3bCdparanoiaLib) " << start << " and " << end << " out of range." << endl; + return false; + } + } + else { + kdDebug() << "(K3bCdparanoiaLib) initReading without initParanoia." << endl; + return false; + } +} + + +char* K3bCdparanoiaLib::read( int* statusCode, unsigned int* track, bool littleEndian ) +{ + if( d->currentSector > d->lastSector ) { + kdDebug() << "(K3bCdparanoiaLib) finished ripping. read " + << (d->currentSector - d->startSector) << " sectors." << endl + << " current sector: " << d->currentSector << endl; + d->status = S_OK; + if( statusCode ) + *statusCode = d->status; + return 0; + } + + if( d->currentSector != d->data->sector() ) { + kdDebug() << "(K3bCdparanoiaLib) need to seek before read. Looks as if we are reusing the paranoia instance." << endl; + if( !d->data->paranoiaSeek( d->currentSector, SEEK_SET ) ) + return 0; + } + + // + // The paranoia data could have been used by someone else before + // and setting the paranoia mode is fast + // + d->updateParanoiaMode(); + + Q_INT16* data = d->data->paranoiaRead( paranoiaCallback, d->maxRetries ); + + char* charData = reinterpret_cast(data); + +#ifdef WORDS_BIGENDIAN // __BYTE_ORDER == __BIG_ENDIAN + if( littleEndian ) { +#else + if( !littleEndian ) { +#endif + for( int i = 0; i < CD_FRAMESIZE_RAW-1; i+=2 ) { + char b = charData[i]; + charData[i] = charData[i+1]; + charData[i+1] = b; + } + } + + + if( data ) + d->status = S_OK; + else + d->status = S_ERROR; // We may skip this sector if we'd like... + + if( statusCode ) + *statusCode = d->status; + + if( track ) + *track = d->currentTrack; + + d->currentSector++; + + if( d->toc[d->currentTrack-1].lastSector() < d->currentSector ) + d->currentTrack++; + + return charData; +} + + +int K3bCdparanoiaLib::status() const +{ + return d->status; +} + + +const K3bDevice::Toc& K3bCdparanoiaLib::toc() const +{ + return d->toc; +} + + +long K3bCdparanoiaLib::rippedDataLength() const +{ + return d->lastSector - d->startSector + 1; +} + + +void K3bCdparanoiaLib::setParanoiaMode( int m ) +{ + d->paranoiaLevel = m; +} + + +void K3bCdparanoiaLib::setNeverSkip( bool b ) +{ + d->neverSkip = b; +} + + +void K3bCdparanoiaLib::setMaxRetries( int r ) +{ + d->maxRetries = r; +} diff --git a/libk3b/tools/k3bcdparanoialib.h b/libk3b/tools/k3bcdparanoialib.h new file mode 100644 index 0000000..70504de --- /dev/null +++ b/libk3b/tools/k3bcdparanoialib.h @@ -0,0 +1,161 @@ +/* + * + * $Id: k3bcdparanoialib.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3B_CDPARANOIA_LIB_H +#define K3B_CDPARANOIA_LIB_H + +// from cdda_interface.h +#define CD_FRAMESIZE_RAW 2352 + + +#include + +#include +#include "k3b_export.h" + +namespace K3bDevice { + class Device; + class Toc; +} + + +/** + * K3bCdparanoiaLib is a convenience wrapper around libcdda_interface + * and libcdda_paranoia. + * + * It uses four paranoia levels 0-3 which can be set via setParanoiaMode + * and are used the same way as in cdrdao: + * \li 0: No checking, data is copied directly from the drive. + * \li 1: Perform overlapped reading to avoid jitter. + * \li 2: Like 1 but with additional checks of the read audio data. + * \li 3: Like 2 but with additional scratch detection and repair. + * + * K3bCdparanoiaLib is based on a shared data approach which makes sure + * that each device can only be opened once. This is necessary since + * libcdda_interface opens the device exclusively on most distributions. + * + * However, it is perfectly possible to have two instances of K3bCdparanoiaLib + * accessing the same device at the same time. K3bCdparanoiaLib will take care + * of the syncing and seeking issues automatically. + * + * K3bCdparanoiaLib is thread-safe. + * + * Usage: + *

+ * K3bCdparanoiaLib lib;
+ * lib.initParanoia( mydevice );
+ * lib.initReading( tracknumber );
+ * while( char* data = lib.read() )
+ *   dosomethingcoolwithdata( data );
+ * 
+ */ +class LIBK3B_EXPORT K3bCdparanoiaLib +{ + public: + ~K3bCdparanoiaLib(); + + /** default: 1 */ + void setParanoiaMode( int ); + void setNeverSkip( bool b ); + + /** default: 5 */ + void setMaxRetries( int ); + + /** + * This will read the Toc and initialize some stuff. + * It will also call paranoiaInit( const QString& ) + */ + bool initParanoia( K3bDevice::Device* dev ); + + /** + * Use for faster initialization without reading the toc + */ + bool initParanoia( K3bDevice::Device* dev, const K3bDevice::Toc& ); + + void close(); + + /** + * Call this after initParanoia to set the data to rip. + * + * Rip all audio tracks. + */ + bool initReading(); + + /** + * Call this after initParanoia to set the data to rip. + */ + bool initReading( unsigned int track ); + + /** + * Call this after initParanoia to set the data to rip. + */ + bool initReading( long startSector, long endSector ); + + /** + * Read data. + * \param statusCode If not 0 will be set. + * \param track the tracknumer the data belongs to + * + * This method takes care of swapping the byte-order depending on the + * machine type. + * + * \return The read sector data or 0 if all data within the specified range + * has been read or an error has occured. + */ + char* read( int* statusCode = 0, unsigned int* track = 0, bool littleEndian = true ); + + /** + * This only is valid after a call to read() + */ + int status() const; + + enum Status { + S_OK, + S_ERROR + // to be extended with Jitter and stuff... + }; + + /** + * Only valid after a call to initParanoia() + */ + const K3bDevice::Toc& toc() const; + + long rippedDataLength() const; + + /** + * returns 0 if the cdparanoialib could not + * be found on the system. + * Otherwise you have to take care of + * deleting. + */ + static K3bCdparanoiaLib* create(); + + private: + void cleanup(); + + K3bCdparanoiaLib(); + bool load(); + + class Private; + Private* d; + + static void* s_libInterface; + static void* s_libParanoia; + static int s_counter; +}; + + +#endif diff --git a/libk3b/tools/k3bcdtextvalidator.cpp b/libk3b/tools/k3bcdtextvalidator.cpp new file mode 100644 index 0000000..8b3c97a --- /dev/null +++ b/libk3b/tools/k3bcdtextvalidator.cpp @@ -0,0 +1,42 @@ +/* + * + * $Id: k3bcdtextvalidator.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bcdtextvalidator.h" + +K3bCdTextValidator::K3bCdTextValidator(QObject *parent, const char *name) + : K3bLatin1Validator(parent, name) +{ +} + + +K3bCdTextValidator::~K3bCdTextValidator() +{ +} + + +QValidator::State K3bCdTextValidator::validate( QString& input, int& pos ) const +{ + if( input.length() > 160 ) + return Invalid; + + // forbid some characters that might introduce problems + for( unsigned int i = 0; i < input.length(); ++i ) { + if( input[i] == '/' || input[i] == '"' || input[i] == '\\' ) + return Invalid; + } + + return K3bLatin1Validator::validate( input, pos ); +} diff --git a/libk3b/tools/k3bcdtextvalidator.h b/libk3b/tools/k3bcdtextvalidator.h new file mode 100644 index 0000000..48ada05 --- /dev/null +++ b/libk3b/tools/k3bcdtextvalidator.h @@ -0,0 +1,33 @@ +/* + * + * $Id: k3bcdtextvalidator.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3BCDTEXTVALIDATOR_H_ +#define _K3BCDTEXTVALIDATOR_H_ + + +#include +#include "k3b_export.h" + +class LIBK3B_EXPORT K3bCdTextValidator : public K3bLatin1Validator +{ + public: + K3bCdTextValidator(QObject *parent = 0, const char *name = 0); + ~K3bCdTextValidator(); + + State validate( QString& input, int& pos ) const; +}; + +#endif diff --git a/libk3b/tools/k3bchecksumpipe.cpp b/libk3b/tools/k3bchecksumpipe.cpp new file mode 100644 index 0000000..21d308a --- /dev/null +++ b/libk3b/tools/k3bchecksumpipe.cpp @@ -0,0 +1,99 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bchecksumpipe.h" + +#include +#include + +#include + + +class K3bChecksumPipe::Private +{ +public: + Private() + : checksumType(MD5) { + } + + void update( const char* in, int len ) { + switch( checksumType ) { + case MD5: + md5.update( in, len ); + break; + } + } + + void reset() { + switch( checksumType ) { + case MD5: + md5.reset(); + break; + } + } + + int checksumType; + + KMD5 md5; +}; + + +K3bChecksumPipe::K3bChecksumPipe() + : K3bActivePipe() +{ + d = new Private(); +} + + +K3bChecksumPipe::~K3bChecksumPipe() +{ + delete d; +} + + +bool K3bChecksumPipe::open( bool closeWhenDone ) +{ + return open( MD5, closeWhenDone ); +} + + +bool K3bChecksumPipe::open( Type type, bool closeWhenDone ) +{ + if( K3bActivePipe::open( closeWhenDone ) ) { + d->reset(); + d->checksumType = type; + return true; + } + else + return false; +} + + +QCString K3bChecksumPipe::checksum() const +{ + switch( d->checksumType ) { + case MD5: + return d->md5.hexDigest(); + } + + return QCString(); +} + + +int K3bChecksumPipe::write( char* data, int max ) +{ + d->update( data, max ); + return K3bActivePipe::write( data, max ); +} diff --git a/libk3b/tools/k3bchecksumpipe.h b/libk3b/tools/k3bchecksumpipe.h new file mode 100644 index 0000000..88adc74 --- /dev/null +++ b/libk3b/tools/k3bchecksumpipe.h @@ -0,0 +1,66 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_CHECKSUM_PIPE_H_ +#define _K3B_CHECKSUM_PIPE_H_ + +#include + +#include + + +/** + * The checksum pipe calculates the checksum of the data + * passed through it. + */ +class LIBK3B_EXPORT K3bChecksumPipe : public K3bActivePipe +{ + public: + K3bChecksumPipe(); + ~K3bChecksumPipe(); + + enum Type { + MD5 + }; + + /** + * \reimplemented + * Defaults to MD5 checksum + */ + bool open( bool closeWhenDone = false ); + + /** + * Opens the pipe and thus starts the + * checksum calculation + * + * \param closeWhenDone If true the pipes will be closed + * once all data has been read. + */ + bool open( Type type, bool closeWhenDone = false ); + + /** + * Get the calculated checksum + */ + QCString checksum() const; + + protected: + int write( char* data, int max ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bcutcombobox.cpp b/libk3b/tools/k3bcutcombobox.cpp new file mode 100644 index 0000000..d4f516b --- /dev/null +++ b/libk3b/tools/k3bcutcombobox.cpp @@ -0,0 +1,230 @@ +/* + * + * $Id: k3bcutcombobox.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bcutcombobox.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +class K3bCutComboBox::Private +{ +public: + Private() { + method = CUT; + } + + QStringList originalItems; + + int method; + int width; +}; + + +K3bCutComboBox::K3bCutComboBox( QWidget* parent, const char* name ) + : KComboBox( parent, name ) +{ + d = new Private(); + // setSizePolicy( QSizePolicy::Maximum, sizePolicy().horData(), sizePolicy().hasHeightForWidth() ); +} + + +K3bCutComboBox::K3bCutComboBox( int method, QWidget* parent, const char* name ) + : KComboBox( parent, name ) +{ + d = new Private(); + d->method = method; +} + + +K3bCutComboBox::~K3bCutComboBox() +{ + delete d; +} + + +void K3bCutComboBox::setMethod( int m ) +{ + d->method = m; + cutText(); +} + + +QSize K3bCutComboBox::sizeHint() const +{ +// QSize s(KComboBox::sizeHint()); + +// for( int i = 0; i < count(); i++ ) { +// int w = fontMetrics().width(d->originalItems[i]) + +// ( d->pixmaps[i].isNull() ? 0 : d->pixmaps[i].width() + 4); +// if( w > s.width() ) +// s.setWidth( w ); +// } + + return KComboBox::sizeHint(); +} + +QSize K3bCutComboBox::minimumSizeHint() const +{ + return KComboBox::minimumSizeHint(); +} + + +void K3bCutComboBox::setCurrentText( const QString& s ) +{ + int i; + for( i = 0; i < count(); i++ ) + if ( d->originalItems[i] == s ) + break; + if ( i < count() ) { + setCurrentItem(i); + } + else if( !d->originalItems.isEmpty() ) { + d->originalItems[currentItem()] = s; + cutText(); + } +} + + +void K3bCutComboBox::insertStringList( const QStringList&, int ) +{ + // FIXME +} + + +void K3bCutComboBox::insertStrList( const QStrList&, int ) +{ + // FIXME +} + +void K3bCutComboBox::insertStrList( const QStrList*, int ) +{ + // FIXME +} + +void K3bCutComboBox::insertStrList( const char**, int, int) +{ + // FIXME +} + +void K3bCutComboBox::insertItem( const QString& text, int index ) +{ + insertItem( QPixmap(), text, index ); +} + +void K3bCutComboBox::insertItem( const QPixmap& pix, int i ) +{ + insertItem( pix, "", i ); +} + +void K3bCutComboBox::insertItem( const QPixmap& pixmap, const QString& text, int index ) +{ + if( index != -1 ) + d->originalItems.insert( d->originalItems.at(index), text ); + else + d->originalItems.append( text ); + + if( !pixmap.isNull() ) + KComboBox::insertItem( pixmap, "xx", index ); + else + KComboBox::insertItem( "xx", index ); + + cutText(); +} + +void K3bCutComboBox::removeItem( int i ) +{ + d->originalItems.erase( d->originalItems.at(i) ); + KComboBox::removeItem( i ); +} + +void K3bCutComboBox::changeItem( const QString& s, int i ) +{ + d->originalItems[i] = s; + cutText(); +} + +void K3bCutComboBox::changeItem( const QPixmap& pix, const QString& s, int i ) +{ + KComboBox::changeItem( pix, i ); + changeItem( s, i ); +} + + +QString K3bCutComboBox::text( int i ) const +{ + if( i < (int)d->originalItems.count() ) + return d->originalItems[i]; + else + return QString::null; +} + + +QString K3bCutComboBox::currentText() const +{ + if( currentItem() < (int)d->originalItems.count() ) + return d->originalItems[currentItem()]; + else + return QString::null; +} + + +void K3bCutComboBox::clear() +{ + KComboBox::clear(); + d->originalItems.clear(); +} + +void K3bCutComboBox::resizeEvent( QResizeEvent* e ) +{ + cutText(); + + KComboBox::resizeEvent(e); +} + + +void K3bCutComboBox::cutText() +{ + d->width = QStyle::visualRect( style().querySubControlMetrics(QStyle::CC_ComboBox, this, + QStyle::SC_ComboBoxEditField), this ).width(); + + for( int i = 0; i < (int)d->originalItems.count(); ++i ) { + int w = d->width; + if ( pixmap(i) && !pixmap(i)->isNull() ) + w -= ( pixmap(i)->width() + 4 ); + + QString text; + if( d->method == SQUEEZE ) + text = K3b::squeezeTextToWidth( fontMetrics(), d->originalItems[i], w ); + else + text = K3b::cutToWidth( fontMetrics(), d->originalItems[i], w ); + + // now insert the cut text + if( pixmap(i) ) + KComboBox::changeItem( *pixmap(i), text, i ); + else + KComboBox::changeItem( text, i ); + } +} + +#include "k3bcutcombobox.moc" diff --git a/libk3b/tools/k3bcutcombobox.h b/libk3b/tools/k3bcutcombobox.h new file mode 100644 index 0000000..1c35e78 --- /dev/null +++ b/libk3b/tools/k3bcutcombobox.h @@ -0,0 +1,92 @@ +/* + * + * $Id: k3bcutcombobox.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_CUT_COMBOBOX_H_ +#define _K3B_CUT_COMBOBOX_H_ + +#include +#include "k3b_export.h" +class QResizeEvent; + + +/** + * Cuts it's text. + * Since it rebuilds the complete list of strings every time + * a new string is added or one gets removed it is not a good + * idea to use this for dynamic lists. + * + * Be aware that currently only insertItem works. + * none of the insertStrList or insertStringList methods are implemeted + * yet and also the removeItem methos does not work. + */ +class LIBK3B_EXPORT K3bCutComboBox : public KComboBox +{ + Q_OBJECT + + public: + K3bCutComboBox( QWidget* parent = 0, const char* name = 0 ); + K3bCutComboBox( int method, QWidget* parent = 0, const char* name = 0 ); + virtual ~K3bCutComboBox(); + + enum Method { + CUT, + SQUEEZE + }; + + /** + * The method to shorten the text + * defaut: CUT + */ + void setMethod( int ); + + /** reimplemeted */ + QSize sizeHint() const; + + /** reimplemeted */ + QSize minimumSizeHint() const; + + /** reimplemeted */ + virtual void setCurrentText( const QString& ); + + void insertStringList( const QStringList &, int index=-1 ); + void insertStrList( const QStrList &, int index=-1 ); + void insertStrList( const QStrList *, int index=-1 ); + void insertStrList( const char **, int numStrings=-1, int index=-1); + + void insertItem( const QString &text, int index=-1 ); + void insertItem( const QPixmap &pixmap, int index=-1 ); + void insertItem( const QPixmap &pixmap, const QString &text, int index=-1 ); + + void removeItem( int index ); + + void changeItem( const QString &text, int index ); + void changeItem( const QPixmap &pixmap, const QString &text, int index ); + + QString text( int ) const; + QString currentText() const; + + void clear(); + + protected: + void resizeEvent( QResizeEvent* e ); + void cutText(); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bdevicecombobox.cpp b/libk3b/tools/k3bdevicecombobox.cpp new file mode 100644 index 0000000..165b59d --- /dev/null +++ b/libk3b/tools/k3bdevicecombobox.cpp @@ -0,0 +1,174 @@ +/* + * + * $Id: k3bdevicecombobox.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bdevicecombobox.h" +#include +#include +#include + +#include + +#include +#include + + +class K3bDeviceComboBox::Private +{ +public: + QMap deviceIndexMap; + QPtrVector devices; +}; + + +K3bDeviceComboBox::K3bDeviceComboBox( QWidget* parent, const char* name ) + : KComboBox( parent, name ) +{ + d = new Private(); + connect( this, SIGNAL(activated(int)), + this, SLOT(slotActivated(int)) ); + connect( k3bcore->deviceManager(), SIGNAL(changed(K3bDevice::DeviceManager*)), + this, SLOT(slotDeviceManagerChanged(K3bDevice::DeviceManager*)) ); +} + + +K3bDeviceComboBox::~K3bDeviceComboBox() +{ + delete d; +} + +K3bDevice::Device* K3bDeviceComboBox::selectedDevice() const +{ + if ( count() > 0 ) + return d->devices[currentItem()]; + else + return 0; +} + + +void K3bDeviceComboBox::addDevice( K3bDevice::Device* dev ) +{ + int devIndex = -2; + bool addDevice = false; + for( int i = 0; i < count(); ++i ) { + if( dev->vendor() == d->devices[i]->vendor() && + dev->description() == d->devices[i]->description() ) { + addDevice = true; + if( devIndex < -1 ) // when devIndex == -1 we already found two devices. + devIndex = i; + else + devIndex = -1; // when there are already two or more equal devices they have already been updated + } + } + + // update the existing device item + if( devIndex >= 0 ) { + changeItem( d->devices[devIndex]->vendor() + " " + + d->devices[devIndex]->description() + + " (" + d->devices[devIndex]->blockDeviceName() + ")", + devIndex ); + d->deviceIndexMap[d->devices[devIndex]->devicename()] = devIndex; + } + + // add the new device item + if( addDevice ) + insertItem( dev->vendor() + " " + dev->description() + " (" + dev->blockDeviceName() + ")" ); + else + insertItem( dev->vendor() + " " + dev->description() ); + + d->deviceIndexMap[dev->devicename()] = count()-1; + d->devices.resize( count() ); + d->devices.insert(count()-1, dev); +} + + +void K3bDeviceComboBox::removeDevice( K3bDevice::Device* dev ) +{ + if( dev ) { + if( d->deviceIndexMap.contains(dev->devicename()) ) { + // let's make it easy and recreate the whole list + K3bDevice::Device* selDev = selectedDevice(); + QPtrList devices; + for( unsigned int i = 0; i < d->devices.size(); ++i ) + devices.append( d->devices[i] ); + + clear(); + + devices.removeRef( dev ); + + addDevices( devices ); + setSelectedDevice( selDev ); + } + } +} + + +void K3bDeviceComboBox::addDevices( const QPtrList& list ) +{ + for( QPtrListIterator it( list ); + it.current(); ++it ) + addDevice( it.current() ); +} + + +void K3bDeviceComboBox::refreshDevices( const QPtrList& list ) +{ + K3bDevice::Device* selDev = selectedDevice(); + clear(); + if( !list.containsRef( selDev ) ) + selDev = 0; + addDevices( list ); + setSelectedDevice( selDev ); +} + + +void K3bDeviceComboBox::setSelectedDevice( K3bDevice::Device* dev ) +{ + if( dev ) { + if( d->deviceIndexMap.contains(dev->devicename()) ) { + setCurrentItem( d->deviceIndexMap[dev->devicename()] ); + emit selectionChanged( dev ); + } + } +} + + +void K3bDeviceComboBox::clear() +{ + d->deviceIndexMap.clear(); + d->devices.clear(); + KComboBox::clear(); +} + + +void K3bDeviceComboBox::slotActivated( int i ) +{ + emit selectionChanged( d->devices[i] ); +} + + +void K3bDeviceComboBox::slotDeviceManagerChanged( K3bDevice::DeviceManager* dm ) +{ + unsigned int i = 0; + while( i < d->devices.size() ) { + if( !dm->allDevices().containsRef( d->devices[i] ) ) { + removeDevice( d->devices[i] ); + i = 0; + } + else + ++i; + } +} + +#include "k3bdevicecombobox.moc" diff --git a/libk3b/tools/k3bdevicecombobox.h b/libk3b/tools/k3bdevicecombobox.h new file mode 100644 index 0000000..5a9cb85 --- /dev/null +++ b/libk3b/tools/k3bdevicecombobox.h @@ -0,0 +1,67 @@ +/* + * + * $Id: k3bdevicecombobox.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_DEVICE_COMBO_BOX_H_ +#define _K3B_DEVICE_COMBO_BOX_H_ + +#include +#include "k3b_export.h" + +namespace K3bDevice { + class Device; + class DeviceManager; +} + + +/** + * A combobox to select a K3b device. + * + * It automatically removes devices that are removed from the system. + */ +class LIBK3B_EXPORT K3bDeviceComboBox : public KComboBox +{ + Q_OBJECT + + public: + K3bDeviceComboBox( QWidget* parent = 0, const char* name = 0 ); + ~K3bDeviceComboBox(); + + K3bDevice::Device* selectedDevice() const; + + signals: + void selectionChanged( K3bDevice::Device* ); + + public slots: + void addDevice( K3bDevice::Device* ); + void addDevices( const QPtrList& ); + /** + * Clears the device combo and tries to keep the current selection + */ + void refreshDevices( const QPtrList& ); + void removeDevice( K3bDevice::Device* ); + void setSelectedDevice( K3bDevice::Device* ); + void clear(); + + private slots: + void slotActivated( int ); + void slotDeviceManagerChanged( K3bDevice::DeviceManager* dm ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bdevicehandler.cpp b/libk3b/tools/k3bdevicehandler.cpp new file mode 100644 index 0000000..c77f1e6 --- /dev/null +++ b/libk3b/tools/k3bdevicehandler.cpp @@ -0,0 +1,332 @@ +/* + * + * $Id: k3bdevicehandler.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bdevicehandler.h" +#include +#include +#include +#include + + + +class K3bDevice::DeviceHandler::DeviceHandlerThread : public K3bThread +{ +public: + DeviceHandlerThread() + : K3bThread(), + dev(0) { + } + + + void run() { + success = false; + m_bCanceled = false; + + // clear data + toc.clear(); + ngInfo = DiskInfo(); + cdText.clear(); + cdTextRaw.resize(0); + + if( dev ) { + success = dev->open(); + if( !m_bCanceled && command & DISKINFO ) { + ngInfo = dev->diskInfo(); + if( !m_bCanceled && !ngInfo.empty() ) { + toc = dev->readToc(); + if( toc.contentType() == AUDIO || + toc.contentType() == MIXED ) + cdText = dev->readCdText(); + } + } + + if( !m_bCanceled && command & (NG_DISKINFO| + DISKSIZE| + REMAININGSIZE| + NUMSESSIONS) ) { + ngInfo = dev->diskInfo(); + } + + if( !m_bCanceled && command & (TOC|TOCTYPE) ) { + toc = dev->readToc(); + } + + if( !m_bCanceled && command & CD_TEXT ) { + cdText = dev->readCdText(); + success = (success && !cdText.isEmpty()); + } + + if( !m_bCanceled && command & CD_TEXT_RAW ) { + unsigned char* data = 0; + unsigned int dataLen = 0; + if( dev->readTocPmaAtip( &data, dataLen, 5, false, 0 ) ) { + // we need more than the header and a multiple of 18 bytes to have valid CD-TEXT + if( dataLen > 4 && dataLen%18 == 4 ) { + cdTextRaw.assign( reinterpret_cast(data), dataLen ); + } + else { + kdDebug() << "(K3bDevice::DeviceHandler) invalid CD-TEXT length: " << dataLen << endl; + delete [] data; + success = false; + } + } + else + success = false; + } + + if( !m_bCanceled && command & BLOCK ) + success = (success && dev->block( true )); + + if( !m_bCanceled && command & UNBLOCK ) + success = (success && dev->block( false )); + + // + // It is important that eject is performed before load + // since the RELOAD command is a combination of both + // + + if( !m_bCanceled && command & EJECT ) + success = (success && dev->eject()); + + if( !m_bCanceled && command & LOAD ) + success = (success && dev->load()); + + if( !m_bCanceled && command & BUFFER_CAPACITY ) + success = dev->readBufferCapacity( bufferCapacity, availableBufferCapacity ); + + dev->close(); + } + + // + // This thread only gets cancelled if a new request was started. + // So we don't emit the finished signal for this (old) request. + // + if( !m_bCanceled ) + emitFinished(success); + } + + void cancel() { + m_bCanceled = true; + } + + + bool success; + int errorCode; + int command; + DiskInfo ngInfo; + Toc toc; + CdText cdText; + QByteArray cdTextRaw; + long long bufferCapacity; + long long availableBufferCapacity; + Device* dev; + +private: + bool m_bCanceled; +}; + + +K3bDevice::DeviceHandler::DeviceHandler( Device* dev, QObject* parent, const char* name ) + : K3bThreadJob( 0, parent, name ), + m_selfDelete(false) +{ + m_thread = new DeviceHandlerThread(); + m_thread->dev = dev; + setThread( m_thread ); +} + + +K3bDevice::DeviceHandler::DeviceHandler( QObject* parent, const char* name ) + : K3bThreadJob( 0, parent, name ), + m_selfDelete(false) +{ + m_thread = new DeviceHandlerThread(); + setThread( m_thread ); +} + + +K3bDevice::DeviceHandler::DeviceHandler( int command, Device* dev, const char* name ) + : K3bThreadJob( 0, 0, name ), + m_selfDelete(true) +{ + m_thread = new DeviceHandlerThread(); + setThread( m_thread ); + m_thread->dev = dev; + sendCommand(command); +} + +K3bDevice::DeviceHandler::~DeviceHandler() +{ + delete m_thread; +} + + +int K3bDevice::DeviceHandler::errorCode() const +{ + return m_thread->errorCode; +} + +bool K3bDevice::DeviceHandler::success() const +{ + return m_thread->success; +} + + +const K3bDevice::DiskInfo& K3bDevice::DeviceHandler::diskInfo() const +{ + return m_thread->ngInfo; +} + + +const K3bDevice::Toc& K3bDevice::DeviceHandler::toc() const +{ + return m_thread->toc; +} + +const K3bDevice::CdText& K3bDevice::DeviceHandler::cdText() const +{ + return m_thread->cdText; +} + + +const QByteArray& K3bDevice::DeviceHandler::cdTextRaw() const +{ + return m_thread->cdTextRaw; +} + + +K3b::Msf K3bDevice::DeviceHandler::diskSize() const +{ + return m_thread->ngInfo.capacity(); +} + +K3b::Msf K3bDevice::DeviceHandler::remainingSize() const +{ + return m_thread->ngInfo.remainingSize(); +} + +int K3bDevice::DeviceHandler::tocType() const +{ + return m_thread->toc.contentType(); +} + +int K3bDevice::DeviceHandler::numSessions() const +{ + return m_thread->ngInfo.numSessions(); +} + +long long K3bDevice::DeviceHandler::bufferCapacity() const +{ + return m_thread->bufferCapacity; +} + +long long K3bDevice::DeviceHandler::availableBufferCapacity() const +{ + return m_thread->availableBufferCapacity; +} + +void K3bDevice::DeviceHandler::setDevice( Device* dev ) +{ + m_thread->dev = dev; +} + + + +void K3bDevice::DeviceHandler::sendCommand( int command ) +{ + // + // We do not want the finished signal emitted in case the devicehandler was cancelled. This is a special case. + // That's why we do not use K3bThreadJob::start() becasue otherwise we would be registered twice. + // + if( m_thread->running() ) { + kdDebug() << "(K3bDevice::DeviceHandler) thread already running. canceling thread..." << endl; + m_thread->cancel(); + m_thread->wait(); + } + else + jobStarted(); + + kdDebug() << "(K3bDevice::DeviceHandler) starting command: " << command << endl; + + m_thread->command = command; + m_thread->start(); +} + +void K3bDevice::DeviceHandler::getToc() +{ + sendCommand(DeviceHandler::TOC); +} + +void K3bDevice::DeviceHandler::getDiskInfo() +{ + sendCommand(DeviceHandler::DISKINFO); +} + +void K3bDevice::DeviceHandler::getDiskSize() +{ + sendCommand(DeviceHandler::DISKSIZE); +} + +void K3bDevice::DeviceHandler::getRemainingSize() +{ + sendCommand(DeviceHandler::REMAININGSIZE); +} + +void K3bDevice::DeviceHandler::getTocType() +{ + sendCommand(DeviceHandler::TOCTYPE); +} + +void K3bDevice::DeviceHandler::getNumSessions() +{ + sendCommand(DeviceHandler::NUMSESSIONS); +} + + +void K3bDevice::DeviceHandler::block( bool b ) +{ + sendCommand(b ? DeviceHandler::BLOCK : DeviceHandler::UNBLOCK); +} + +void K3bDevice::DeviceHandler::eject() +{ + sendCommand(DeviceHandler::EJECT); +} + +K3bDevice::DeviceHandler* K3bDevice::sendCommand( int command, Device* dev ) +{ + return new DeviceHandler( command, dev, "DeviceHandler" ); +} + +void K3bDevice::DeviceHandler::customEvent( QCustomEvent* e ) +{ + K3bThreadJob::customEvent(e); + + if( (int)e->type() == K3bProgressInfoEvent::Finished ) { + emit finished( this ); + if( m_selfDelete ) { + kdDebug() << "(K3bDevice::DeviceHandler) thread emitted finished. Waiting for thread actually finishing" << endl; + kdDebug() << "(K3bDevice::DeviceHandler) success: " << m_thread->success << endl; + // wait for the thread to finish + m_thread->wait(); + kdDebug() << "(K3bDevice::DeviceHandler) deleting thread." << endl; + deleteLater(); + } + } +} + + +#include "k3bdevicehandler.moc" diff --git a/libk3b/tools/k3bdevicehandler.h b/libk3b/tools/k3bdevicehandler.h new file mode 100644 index 0000000..d5159a0 --- /dev/null +++ b/libk3b/tools/k3bdevicehandler.h @@ -0,0 +1,237 @@ +/* + * + * $Id: k3bdevicehandler.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_DEVICE_HANDLER_H_ +#define _K3B_DEVICE_HANDLER_H_ + +#include +#include "k3bdevice.h" +#include "k3bdiskinfo.h" +#include "k3bmsf.h" +#include "k3bcdtext.h" +#include "k3b_export.h" +#include + +class QCustomEvent; + + +namespace K3bDevice +{ + class Device; + + + /** + * The K3bDevice::Devicehandler is a threaded wrapper around K3bDevice::Device. + * It allows async access to the time comsuming blocking K3bDevice::Device methods. + * Since it's a K3bJob it is very easy to handle. Just use one of the methods and + * connect to the finished signal. + * Be aware that all methods only return valid values if the corresponding info has + * been successfuly requested. + * + * Be aware that multiple requests in a row (without waiting for the job to finish) will + * only result in one finished() signal answering the last request. + */ + class LIBK3B_EXPORT DeviceHandler : public K3bThreadJob + { + Q_OBJECT + + public: + DeviceHandler( Device*, QObject* parent = 0, const char* name = 0 ); + DeviceHandler( QObject* parent = 0, const char* name = 0 ); + + /** + * This constructor is used by the global "quick" methods and should not be used + * otherwise except for the same usage. + */ + DeviceHandler( int command, Device*, const char* name = 0 ); + + ~DeviceHandler(); + + const DiskInfo& diskInfo() const; + const Toc& toc() const; + const CdText& cdText() const; + const QByteArray& cdTextRaw() const; + K3b::Msf diskSize() const; + K3b::Msf remainingSize() const; + int tocType() const; + int numSessions() const; + long long bufferCapacity() const; + long long availableBufferCapacity() const; + + bool success() const; + + /** + * Use this when the command + * returnes some error code. + */ + int errorCode() const; + + enum Command { + /** + * Always successful, even with an empty or no media at all! + */ + NG_DISKINFO = 1, // TODO: rename this into DISKINFO + /** + * Always successful, even with an empty or no media at all! + */ + TOC = 2, + /** + * Successful if the media contains CD-Text. + */ + CD_TEXT = 4, + /** + * Successful if the media contains CD-Text. + */ + CD_TEXT_RAW = 8, + /** + * Always successful, even with an empty or no media at all! + */ + DISKSIZE = 16, + /** + * Always successful, even with an empty or no media at all! + */ + REMAININGSIZE = 32, + /** + * Always successful, even with an empty or no media at all! + */ + TOCTYPE = 64, + /** + * Always successful, even with an empty or no media at all! + */ + NUMSESSIONS = 128, + /** + * Successful if the drive could be blocked. + */ + BLOCK = 256, + /** + * Successful if the drive could be unblocked. + */ + UNBLOCK = 512, + /** + * Successful if the media was ejected. + */ + EJECT = 1024, + /** + * Successful if the media was loaded + */ + LOAD = 2048, + RELOAD = EJECT|LOAD, + /** + * Retrieves NG_DISKINFO, TOC, and CD-Text in case of an audio or mixed + * mode cd. + * The only difference to NG_DISKINFO|TOC|CD_TEXT is that no CD-Text is not + * considered an error. + * + * Always successful, even with an empty or no media at all! + */ + DISKINFO = 4096, // TODO: rename this in somthing like: DISKINFO_COMPLETE + /** + * Determine the device buffer state. + */ + BUFFER_CAPACITY = 8192 + }; + + signals: + void finished( K3bDevice::DeviceHandler* ); + + public slots: + void setDevice( Device* ); + void sendCommand( int command ); + + void getToc(); + void getDiskInfo(); + void getDiskSize(); + void getRemainingSize(); + void getTocType(); + void getNumSessions(); + void block( bool ); + void eject(); + + protected: + /** + * reimplemented from K3bThreadJob for internal reasons + */ + virtual void customEvent( QCustomEvent* ); + + private: + class DeviceHandlerThread; + DeviceHandlerThread* m_thread; + + bool m_selfDelete; + }; + + /** + * Usage: + * \code + * connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::MOUNT, dev ), + * SIGNAL(finished(DeviceHandler*)), + * this, SLOT(someSlot(DeviceHandler*)) ); + * + * void someSlot( DeviceHandler* dh ) { + * if( dh->success() ) { + * \endcode + * + * Be aware that the DeviceHandler will get destroyed once the signal has been + * emited. + */ + LIBK3B_EXPORT DeviceHandler* sendCommand( int command, Device* ); + + inline DeviceHandler* diskInfo(Device* dev) { + return sendCommand(DeviceHandler::DISKINFO,dev); + } + + inline DeviceHandler* toc(Device* dev) { + return sendCommand(DeviceHandler::TOC,dev); + } + + inline DeviceHandler* diskSize(Device* dev) { + return sendCommand(DeviceHandler::DISKSIZE,dev); + } + + inline DeviceHandler* remainingSize(Device* dev) { + return sendCommand(DeviceHandler::REMAININGSIZE,dev); + } + + inline DeviceHandler* tocType(Device* dev) { + return sendCommand(DeviceHandler::TOCTYPE,dev); + } + + inline DeviceHandler* numSessions(Device* dev) { + return sendCommand(DeviceHandler::NUMSESSIONS,dev); + } + + inline DeviceHandler* block(Device* dev) { + return sendCommand(DeviceHandler::BLOCK,dev); + } + + inline DeviceHandler* unblock(Device* dev) { + return sendCommand(DeviceHandler::UNBLOCK,dev); + } + + inline DeviceHandler* eject(Device* dev) { + return sendCommand(DeviceHandler::EJECT,dev); + } + + inline DeviceHandler* reload(Device* dev) { + return sendCommand(DeviceHandler::RELOAD,dev); + } + + inline DeviceHandler* load(Device* dev) { + return sendCommand(DeviceHandler::LOAD,dev); + } +} + +#endif diff --git a/libk3b/tools/k3bdeviceselectiondialog.cpp b/libk3b/tools/k3bdeviceselectiondialog.cpp new file mode 100644 index 0000000..d622457 --- /dev/null +++ b/libk3b/tools/k3bdeviceselectiondialog.cpp @@ -0,0 +1,130 @@ +/* + * + * $Id: k3bdeviceselectiondialog.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#include "k3bdeviceselectiondialog.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + +class K3bDeviceSelectionDialog::Private +{ +public: + K3bDeviceComboBox* comboDevices; +}; + + +K3bDeviceSelectionDialog::K3bDeviceSelectionDialog( QWidget* parent, + const char* name, + const QString& text, + bool modal ) + : KDialogBase( KDialogBase::Plain, + i18n("Device Selection"), + Ok|Cancel, + Ok, + parent, + name, + modal ) +{ + d = new Private(); + + QGridLayout* lay = new QGridLayout( plainPage() ); + + QLabel* label = new QLabel( text.isEmpty() ? i18n("Please select a device:") : text, plainPage() ); + d->comboDevices = new K3bDeviceComboBox( plainPage() ); + + // lay->setMargin( marginHint() ); + lay->setSpacing( spacingHint() ); + lay->addWidget( label, 0, 0 ); + lay->addWidget( d->comboDevices, 1, 0 ); + lay->setRowStretch( 2, 1 ); +} + + +K3bDeviceSelectionDialog::~K3bDeviceSelectionDialog() +{ + delete d; +} + + +void K3bDeviceSelectionDialog::addDevice( K3bDevice::Device* dev ) +{ + d->comboDevices->addDevice( dev ); +} + + +void K3bDeviceSelectionDialog::addDevices( const QPtrList& list ) +{ + d->comboDevices->addDevices( list ); +} + + +K3bDevice::Device* K3bDeviceSelectionDialog::selectedDevice() const +{ + return d->comboDevices->selectedDevice(); +} + + +void K3bDeviceSelectionDialog::setSelectedDevice( K3bDevice::Device* dev ) +{ + d->comboDevices->setSelectedDevice( dev ); +} + + +K3bDevice::Device* K3bDeviceSelectionDialog::selectDevice( QWidget* parent, + const QPtrList& devices, + const QString& text ) +{ + if( devices.isEmpty() ) + return 0; + if( devices.count() == 1 ) + return devices.getFirst(); + + K3bDeviceSelectionDialog dlg( parent, 0, text ); + dlg.addDevices( devices ); + + if( dlg.exec() == Accepted ) + return dlg.selectedDevice(); + else + return 0; +} + +K3bDevice::Device* K3bDeviceSelectionDialog::selectDevice( QWidget* parent, + const QString& text ) +{ + return selectDevice( parent, k3bcore->deviceManager()->allDevices(), text ); + + +} + + +K3bDevice::Device* K3bDeviceSelectionDialog::selectWriter( QWidget* parent, const QString& text ) +{ + return selectDevice( parent, k3bcore->deviceManager()->burningDevices(), text ); +} + + +#include "k3bdeviceselectiondialog.moc" diff --git a/libk3b/tools/k3bdeviceselectiondialog.h b/libk3b/tools/k3bdeviceselectiondialog.h new file mode 100644 index 0000000..b61ce1e --- /dev/null +++ b/libk3b/tools/k3bdeviceselectiondialog.h @@ -0,0 +1,62 @@ +/* + * + * $Id: k3bdeviceselectiondialog.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#ifndef K3B_DEVICE_SELECTION_DIALOG_H +#define K3B_DEVICE_SELECTION_DIALOG_H + + +#include +#include "k3b_export.h" +#include + +namespace K3bDevice { + class Device; +} + + +class LIBK3B_EXPORT K3bDeviceSelectionDialog : public KDialogBase +{ + Q_OBJECT + + public: + K3bDeviceSelectionDialog( QWidget* parent = 0, + const char* name = 0, + const QString& text = QString::null, + bool modal = false ); + ~K3bDeviceSelectionDialog(); + + void addDevice( K3bDevice::Device* ); + void addDevices( const QPtrList& ); + + void setSelectedDevice( K3bDevice::Device* ); + + K3bDevice::Device* selectedDevice() const; + + static K3bDevice::Device* selectWriter( QWidget* parent, + const QString& text = QString::null ); + static K3bDevice::Device* selectDevice( QWidget* parent, + const QString& text = QString::null ); + static K3bDevice::Device* selectDevice( QWidget* parent, + const QPtrList& devices, + const QString& text = QString::null ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bdirsizejob.cpp b/libk3b/tools/k3bdirsizejob.cpp new file mode 100644 index 0000000..ab9cb8a --- /dev/null +++ b/libk3b/tools/k3bdirsizejob.cpp @@ -0,0 +1,184 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bdirsizejob.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include + + +class K3bDirSizeJob::WorkThread : public K3bThread +{ +public: + WorkThread() + : K3bThread(), + followSymlinks(false), + totalSize(0), + totalFiles(0), + totalDirs(0), + totalSymlinks(0) { + } + + void init() { + m_canceled = false; + + totalSize = 0; + totalFiles = 0; + totalDirs = 0; + totalSymlinks = 0; + } + + void run() { + emitStarted(); + + QStringList l; + for( KURL::List::const_iterator it = urls.begin(); + it != urls.end(); ++it ) { + const KURL& url = *it; + + if( !url.isLocalFile() ) { + kdDebug() << "(K3bDirSizeJob) no remote support." << endl; + emitFinished( false ); + return; + } + + l.append( url.path() ); + } + + emitFinished( countFiles( l, QString() ) ); + } + + bool countDir( const QString& dir ) { + const QString& dot = KGlobal::staticQString( "." ); + const QString& dotdot = KGlobal::staticQString( ".." ); + QStringList l = QDir(dir).entryList( QDir::All|QDir::Hidden|QDir::System ); + l.remove( dot ); + l.remove( dotdot ); + + return countFiles( l, dir ); + } + + + bool countFiles( const QStringList& l, const QString& dir ) { + for( QStringList::const_iterator it = l.begin(); + it != l.end(); ++it ) { + + if( m_canceled ) + return false; + + k3b_struct_stat s; + if( k3b_lstat( QFile::encodeName( dir + *it ), &s ) ) + return false; + + if( S_ISLNK( s.st_mode ) ) { + ++totalSymlinks; + if( followSymlinks ) { + if( k3b_stat( QFile::encodeName( dir + *it ), &s ) ) + return false; + } + } + + if( S_ISDIR( s.st_mode ) ) { + ++totalDirs; + if( !countDir( dir + *it + '/' ) ) + return false; + } + else if( !S_ISLNK( s.st_mode ) ) { + ++totalFiles; + totalSize += (KIO::filesize_t)s.st_size; + } + } + + return true; + } + + void cancel() { + m_canceled = true; + emitCanceled(); + wait(); + } + + KURL::List urls; + bool followSymlinks; + + KIO::filesize_t totalSize; + KIO::filesize_t totalFiles; + KIO::filesize_t totalDirs; + KIO::filesize_t totalSymlinks; + +private: + bool m_canceled; +}; + + +K3bDirSizeJob::K3bDirSizeJob( QObject* parent ) + : K3bThreadJob( new K3bSimpleJobHandler(), parent ) +{ + d = new WorkThread; + setThread( d ); +} + + +K3bDirSizeJob::~K3bDirSizeJob() +{ + delete d; + delete jobHandler(); +} + + +KIO::filesize_t K3bDirSizeJob::totalSize() const +{ + return d->totalSize; +} + + +KIO::filesize_t K3bDirSizeJob::totalFiles() const +{ + return d->totalFiles; +} + + +KIO::filesize_t K3bDirSizeJob::totalDirs() const +{ + return d->totalDirs; +} + + +KIO::filesize_t K3bDirSizeJob::totalSymlinks() const +{ + return d->totalSymlinks; +} + + +void K3bDirSizeJob::setUrls( const KURL::List& urls ) +{ + d->urls = urls; +} + + +void K3bDirSizeJob::setFollowSymlinks( bool b ) +{ + d->followSymlinks = b; +} + +#include "k3bdirsizejob.moc" diff --git a/libk3b/tools/k3bdirsizejob.h b/libk3b/tools/k3bdirsizejob.h new file mode 100644 index 0000000..d6a3e5a --- /dev/null +++ b/libk3b/tools/k3bdirsizejob.h @@ -0,0 +1,67 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_DIR_SIZE_JOB_H_ +#define _K3B_DIR_SIZE_JOB_H_ + +#include +#include + +#include + +/** + * K3bDirSizeJob is a replacement for KDirSize which allows + * a much finer grained control over what is counted and how. + * Additionally it uses threading for enhanced speed. + * + * For now K3bDirSizeJob only works on local urls. + */ +class LIBK3B_EXPORT K3bDirSizeJob : public K3bThreadJob +{ + Q_OBJECT + + public: + K3bDirSizeJob( QObject* parent = 0 ); + ~K3bDirSizeJob(); + + KIO::filesize_t totalSize() const; + + /** + * Does also include symlinks to files, devices, and fifos + */ + KIO::filesize_t totalFiles() const; + + /** + * Total number of counted dirs. This does also + * include the first dirs the job was started with. + * Does also include symlinks to dirs. + */ + KIO::filesize_t totalDirs() const; + + /** + * Includes symlinks to files and folders + */ + KIO::filesize_t totalSymlinks() const; + + public slots: + void setUrls( const KURL::List& urls ); + void setFollowSymlinks( bool ); + + private: + class WorkThread; + WorkThread* d; +}; + +#endif diff --git a/libk3b/tools/k3bexceptions.cpp b/libk3b/tools/k3bexceptions.cpp new file mode 100644 index 0000000..1d8806f --- /dev/null +++ b/libk3b/tools/k3bexceptions.cpp @@ -0,0 +1,43 @@ +/* + * + * $Id: k3bexceptions.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bexceptions.h" +#include + +bool K3bExceptions::brokenDaoAudio( K3bDevice::Device* dev ) +{ + if( dev->vendor().upper().startsWith("PIONEER") ) + if( dev->description().upper().startsWith("DVR-106D") || + dev->description().upper().startsWith("DVD-RW DVR-K12D") ) + return true; + + if( dev->vendor().upper().startsWith("HL-DT-ST") ) + if( dev->description().upper().startsWith("RW/DVD GCC-4320B") || + dev->description().upper().contains("GCE-8520B") ) + return true; + + if( dev->vendor().upper().startsWith("PHILIPS") && + dev->description().upper().startsWith("CDRWDVD3210") ) + return true; + + if( dev->vendor().upper().startsWith("LITE-ON") ) + if( dev->description().upper().startsWith("LTR-32123S") || + dev->description().upper().startsWith("LTR-40125S") || + dev->description().upper().contains("LTC-48161H") || + dev->description().upper().startsWith("DVDRW LDW-811S") ) + return true; + + return false; +} diff --git a/libk3b/tools/k3bexceptions.h b/libk3b/tools/k3bexceptions.h new file mode 100644 index 0000000..a078992 --- /dev/null +++ b/libk3b/tools/k3bexceptions.h @@ -0,0 +1,35 @@ +/* + * + * $Id: k3bexceptions.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_EXCEPTIONS_H_ +#define _K3B_EXCEPTIONS_H_ + +namespace K3bDevice { + class Device; +} + +class K3bExceptions +{ + public: + /** + * Returns true if the drive's firmware produces broken + * Audio CDs with zero length pregaps. + * + * It simply uses a compiled in table. + */ + static bool brokenDaoAudio( K3bDevice::Device* ); +}; + +#endif diff --git a/libk3b/tools/k3bfilesplitter.cpp b/libk3b/tools/k3bfilesplitter.cpp new file mode 100644 index 0000000..af5b83f --- /dev/null +++ b/libk3b/tools/k3bfilesplitter.cpp @@ -0,0 +1,307 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bfilesplitter.h" +#include "k3bfilesysteminfo.h" + +#include + +#include + + +class K3bFileSplitter::Private +{ +public: + Private( K3bFileSplitter* splitter ) + : m_splitter( splitter ) { + } + + QString filename; + QFile file; + int counter; + + // QIODevice::Offset is too small on most compilations + KIO::filesize_t maxFileSize; + + KIO::filesize_t currentOverallPos; + KIO::filesize_t currentFilePos; + + void determineMaxFileSize() { + if( maxFileSize == 0 ) { + if( K3bFileSystemInfo( filename ).type() == K3bFileSystemInfo::FS_FAT ) + maxFileSize = 1024ULL*1024ULL*1024ULL; // 1GB + else + maxFileSize = 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL; // incredibly big, 1024 TB + } + } + + QString buildFileName( int counter ) { + if( counter > 0 ) + return filename + '.' + QString::number(counter).rightJustify( 3, '0' ); + else + return filename; + } + + QString currentFileName() { + return buildFileName( counter ); + } + + bool openPrevFile() { + return openFile( --counter ); + } + + bool openNextFile() { + return openFile( ++counter ); + } + + bool openFile( int counter ) { + file.close(); + file.setName( buildFileName( counter ) ); + currentFilePos = 0; + if( file.open( m_splitter->mode() ) ) { + m_splitter->setState( IO_Open ); + return true; + } + else { + m_splitter->setState( ~IO_Open ); + return false; + } + } + +private: + K3bFileSplitter* m_splitter; +}; + + +K3bFileSplitter::K3bFileSplitter() +{ + d = new Private( this ); +} + + +K3bFileSplitter::K3bFileSplitter( const QString& filename ) +{ + d = new Private( this ); + setName( filename ); +} + + +K3bFileSplitter::~K3bFileSplitter() +{ + delete d; +} + + +const QString& K3bFileSplitter::name() const +{ + return d->filename; +} + + +void K3bFileSplitter::setName( const QString& filename ) +{ + close(); + d->maxFileSize = 0; + d->filename = filename; +} + + +bool K3bFileSplitter::open( int mode ) +{ + close(); + + d->determineMaxFileSize(); + + d->counter = 0; + d->currentFilePos = 0; + d->currentOverallPos = 0; + setMode( mode ); + + return d->openFile( 0 ); +} + + +void K3bFileSplitter::close() +{ + d->file.close(); + d->counter = 0; + d->currentFilePos = 0; + d->currentOverallPos = 0; +} + + +int K3bFileSplitter::handle() const +{ + // FIXME: use a K3bPipe to simulate this + return -1; +} + + + +void K3bFileSplitter::flush() +{ + d->file.flush(); +} + + +QIODevice::Offset K3bFileSplitter::size() const +{ + // not implemented due to Offset size limitations + return 0; +} + + +QIODevice::Offset K3bFileSplitter::at() const +{ + return d->currentOverallPos; +} + + +bool K3bFileSplitter::at( QIODevice::Offset pos ) +{ + Q_UNUSED( pos ); + // not implemented due to Offset size limitations + return false; +} + + +bool K3bFileSplitter::atEnd() const +{ + return d->file.atEnd() && !QFile::exists( d->buildFileName( d->counter+1 ) ); +} + + +Q_LONG K3bFileSplitter::readBlock( char *data, Q_ULONG maxlen ) +{ + Q_LONG r = d->file.readBlock( data, maxlen ); + if( r == 0 ) { + if( atEnd() ) { + return r; + } + else if( d->openNextFile() ) { + // recursively call us + return readBlock( data, maxlen ); + } + } + else if( r > 0 ) { + d->currentOverallPos += r; + d->currentFilePos += r; + } + + return r; +} + + +Q_LONG K3bFileSplitter::writeBlock( const char *data, Q_ULONG len ) +{ + // We cannot rely on QFile::at since it uses long on most copmpilations + Q_ULONG max = (Q_ULONG)QMIN( (KIO::filesize_t)len, d->maxFileSize - d->currentFilePos ); + + Q_LONG r = d->file.writeBlock( data, max ); + + if( r < 0 ) + return r; + + d->currentOverallPos += r; + d->currentFilePos += r; + + // recursively call us + if( (Q_ULONG)r < len ) { + if( d->openNextFile() ) + return r + writeBlock( data+r, len-r ); + else + return -1; + } + else + return r; +} + + +int K3bFileSplitter::getch() +{ + int r = d->file.getch(); + if( r == -1 ) { + if( !d->file.atEnd() ) { + return -1; + } + else if( !atEnd() ) { + if( !d->openNextFile() ) + return -1; + else + return getch(); + } + } + + d->currentOverallPos++; + d->currentFilePos++; + + return r; +} + + +int K3bFileSplitter::putch( int c ) +{ + if( d->currentFilePos < d->maxFileSize ) { + d->currentOverallPos++; + d->currentFilePos++; + return d->file.putch( c ); + } + else if( d->openNextFile() ) { + // recursively call us + return putch( c ); + } + else + return -1; +} + + +int K3bFileSplitter::ungetch( int c ) +{ + if( d->currentFilePos > 0 ) { + int r = d->file.ungetch( c ); + if( r != -1 ) { + d->currentOverallPos--; + d->currentFilePos--; + } + return r; + } + else if( d->counter > 0 ) { + // open prev file + if( d->openPrevFile() ) { + // seek to the end + d->file.at( d->file.size() ); + d->currentFilePos = d->file.at(); + return getch(); + } + else + return -1; + } + else + return -1; +} + + +void K3bFileSplitter::remove() +{ + close(); + while( QFile::exists( d->buildFileName( d->counter ) ) ) + QFile::remove( d->buildFileName( d->counter++ ) ); +} + + +void K3bFileSplitter::setMaxFileSize( KIO::filesize_t size ) +{ + d->maxFileSize = size; +} diff --git a/libk3b/tools/k3bfilesplitter.h b/libk3b/tools/k3bfilesplitter.h new file mode 100644 index 0000000..22dcad9 --- /dev/null +++ b/libk3b/tools/k3bfilesplitter.h @@ -0,0 +1,108 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_FILE_SPLITTER_H_ +#define _K3B_FILE_SPLITTER_H_ + +#include +#include + +#include + +#include + + +/** + * QFile replacement which splits + * big files according to the underlying file system's + * maximum file size. + * + * The filename will be changed to include a counter + * if the file has to be splitted like so: + * + *
+ * filename.iso
+ * filename.iso.001
+ * filename.iso.002
+ * ...
+ * 
+ */ +class LIBK3B_EXPORT K3bFileSplitter : public QIODevice +{ + public: + K3bFileSplitter(); + K3bFileSplitter( const QString& filename ); + ~K3bFileSplitter(); + + /** + * Set the maximum file size. If this is set to 0 + * (the default) the max filesize is determined based on + * the filesystem type. + * + * Be aware that setName will reset the max file size. + */ + void setMaxFileSize( KIO::filesize_t size ); + + const QString& name() const; + + void setName( const QString& filename ); + + virtual bool open( int mode ); + + virtual void close(); + + /** + * File descriptor to read from and write to. + * Not implemented yet! + */ + int handle() const; + + virtual void flush(); + + /** + * Not implemented + */ + virtual Offset size() const; + + /** + * Not implemented + */ + virtual Offset at() const; + + /** + * Not implemented + */ + virtual bool at( Offset ); + + virtual bool atEnd() const; + virtual Q_LONG readBlock( char *data, Q_ULONG maxlen ); + virtual Q_LONG writeBlock( const char *data, Q_ULONG len ); + virtual int getch(); + virtual int putch( int ); + virtual int ungetch( int ); + + /** + * Deletes all the splitted files. + * Caution: Does remove all files that fit the naming scheme without any + * additional checks. + */ + void remove(); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bfilesysteminfo.cpp b/libk3b/tools/k3bfilesysteminfo.cpp new file mode 100644 index 0000000..fe1eaf8 --- /dev/null +++ b/libk3b/tools/k3bfilesysteminfo.cpp @@ -0,0 +1,141 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include + +#include "k3bfilesysteminfo.h" + +#include + +#include +#include +#include + +#include + +#ifdef Q_OS_FREEBSD +#include +#include +#endif +#ifdef HAVE_SYS_STATVFS_H +# include +# if defined(Q_OS_NETBSD) +# include +# if __NetBSD_Version__ > 299000000 +# define statfs statvfs +# define f_type f_fsid +# endif +# endif +#endif +#ifdef HAVE_SYS_VFS_H +# include +#endif + +#include +#include + + + +class K3bFileSystemInfo::Private +{ +public: + Private() + : type(FS_UNKNOWN), + statDone(false) { + } + + FileSystemType type; + QString path; + + bool statDone; + + void stat() { + struct statfs fs; + if( !::statfs( QFile::encodeName( QFileInfo(path).dirPath( true ) ), &fs ) ) { + switch( fs.f_type ) { + case 0x4d44: // MS-DOS + type = FS_FAT; + default: + type = FS_UNKNOWN; + } + + statDone = true; + } + else { + kdDebug() << "(K3bFileSystemInfo) statfs failed: " << ::strerror(errno) << endl; + } + } +}; + + +K3bFileSystemInfo::K3bFileSystemInfo() +{ + d = new Private; +} + + +K3bFileSystemInfo::K3bFileSystemInfo( const QString& path ) +{ + d = new Private; + d->path = path; +} + + +K3bFileSystemInfo::K3bFileSystemInfo( const K3bFileSystemInfo& other ) +{ + d = new Private; + d->type = other.d->type; + d->path = other.d->path; + d->statDone = other.d->statDone; +} + + +K3bFileSystemInfo::~K3bFileSystemInfo() +{ + delete d; +} + + +QString K3bFileSystemInfo::path() const +{ + return d->path; +} + + +void K3bFileSystemInfo::setPath( const QString& path ) +{ + if( d->path != path ) { + d->path = path; + d->statDone = false; + } +} + + +K3bFileSystemInfo::FileSystemType K3bFileSystemInfo::type() const +{ + if( !d->statDone ) + d->stat(); + return d->type; +} + + +QString K3bFileSystemInfo::fixupPath( const QString& path ) +{ + QString s = K3b::fixupPath( path ); + if( type() == K3bFileSystemInfo::FS_FAT ) + return s.replace( QRegExp("[\"\\?\\*/\\\\[\\]\\|\\=\\:;]"), "_" ); + else + return s; +} diff --git a/libk3b/tools/k3bfilesysteminfo.h b/libk3b/tools/k3bfilesysteminfo.h new file mode 100644 index 0000000..be9995c --- /dev/null +++ b/libk3b/tools/k3bfilesysteminfo.h @@ -0,0 +1,56 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_FILE_SYSTEM_INFO_H_ +#define _K3B_FILE_SYSTEM_INFO_H_ + +#include + +#include + +class LIBK3B_EXPORT K3bFileSystemInfo +{ + public: + K3bFileSystemInfo(); + K3bFileSystemInfo( const QString& path ); + K3bFileSystemInfo( const K3bFileSystemInfo& ); + ~K3bFileSystemInfo(); + + QString path() const; + void setPath( const QString& path ); + + enum FileSystemType { + FS_UNKNOWN, + FS_FAT + // FIXME: add way more file system types + }; + + FileSystemType type() const; + + /** + * Ensures that the file path does not contain + * any invalid chars. + * + * For now it only replaces characters like * or [ + * on FAT file systems. + */ + QString fixupPath( const QString& ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bintmapcombobox.cpp b/libk3b/tools/k3bintmapcombobox.cpp new file mode 100644 index 0000000..19ac649 --- /dev/null +++ b/libk3b/tools/k3bintmapcombobox.cpp @@ -0,0 +1,127 @@ +/* + * + * $Id: k3bwritingmodewidget.cpp 554512 2006-06-24 07:25:39Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bintmapcombobox.h" + +#include +#include +#include + + +class K3bIntMapComboBox::Private +{ +public: + QMap valueIndexMap; + QMap > indexValueDescriptionMap; + + QString topWhatsThis; + QString bottomWhatsThis; +}; + + +K3bIntMapComboBox::K3bIntMapComboBox( QWidget* parent, const char* name ) + : KComboBox( parent, name ) +{ + d = new Private; + connect( this, SIGNAL(highlighted(int)), + this, SLOT(slotItemHighlighted(int)) ); + connect( this, SIGNAL(activated(int)), + this, SLOT(slotItemActivated(int)) ); +} + + +K3bIntMapComboBox::~K3bIntMapComboBox() +{ + delete d; +} + + +int K3bIntMapComboBox::selectedValue() const +{ + if( (int)d->indexValueDescriptionMap.count() > KComboBox::currentItem() ) + return d->indexValueDescriptionMap[KComboBox::currentItem()].first; + else + return 0; +} + + +void K3bIntMapComboBox::setSelectedValue( int value ) +{ + if( d->valueIndexMap.contains( value ) ) + KComboBox::setCurrentItem( d->valueIndexMap[value] ); +} + + +void K3bIntMapComboBox::clear() +{ + d->valueIndexMap.clear(); + d->indexValueDescriptionMap.clear(); + + KComboBox::clear(); +} + + +bool K3bIntMapComboBox::insertItem( int value, const QString& text, const QString& description, int index ) +{ + if( d->valueIndexMap.contains( value ) ) + return false; + + // FIXME: allow inserition at any index + index = KComboBox::count(); + + d->valueIndexMap[value] = index; + d->indexValueDescriptionMap[index] = qMakePair( value, description ); + + KComboBox::insertItem( text ); + + updateWhatsThis(); + + return true; +} + + +void K3bIntMapComboBox::updateWhatsThis() +{ + QString ws( d->topWhatsThis ); + for( unsigned int i = 0; i < d->indexValueDescriptionMap.count(); ++i ) { + ws += "

" + KComboBox::text( i ) + "
"; + ws += d->indexValueDescriptionMap[i].second; + } + ws += "

" + d->bottomWhatsThis; + + QWhatsThis::add( this, ws ); +} + + +void K3bIntMapComboBox::slotItemHighlighted( int index ) +{ + emit valueHighlighted( d->indexValueDescriptionMap[index].first ); +} + + +void K3bIntMapComboBox::slotItemActivated( int index ) +{ + emit valueChanged( d->indexValueDescriptionMap[index].first ); +} + + +void K3bIntMapComboBox::addGlobalWhatsThisText( const QString& top, const QString& bottom ) +{ + d->topWhatsThis = top; + d->bottomWhatsThis = bottom; + updateWhatsThis(); +} + +#include "k3bintmapcombobox.moc" diff --git a/libk3b/tools/k3bintmapcombobox.h b/libk3b/tools/k3bintmapcombobox.h new file mode 100644 index 0000000..b0ae717 --- /dev/null +++ b/libk3b/tools/k3bintmapcombobox.h @@ -0,0 +1,83 @@ +/* + * + * $Id: k3bwritingmodewidget.cpp 554512 2006-06-24 07:25:39Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_INT_MAP_COMBOBOX_H_ +#define _K3B_INT_MAP_COMBOBOX_H_ + +#include + +#include "k3b_export.h" + +/** + * The K3bIntMapComboBox allows a simple selection of integer + * values. + * + * The K3bIntMapComboBox will create a WhatsThis help automatically from + * the description texts (if all are set). The ToolTip has to be set manually. + */ +class LIBK3B_EXPORT K3bIntMapComboBox : public KComboBox +{ + Q_OBJECT + + public: + K3bIntMapComboBox( QWidget* parent = 0, const char* name = 0 ); + ~K3bIntMapComboBox(); + + int selectedValue() const; + + signals: + /** + * Emitted if the selected value changes by user interaction. + */ + void valueChanged( int ); + + /** + * Emitted if the current highlighted value changed by user interaction. + */ + void valueHighlighted( int ); + + public slots: + /** + * If \a v has not been added via insertItem the selection will not be changed + */ + void setSelectedValue( int v ); + + void clear(); + + /** + * Insert a new item + * \param value The integer value to insert + * \param text The text to be displayed in the combobox + * \param description The text to be used to describe the item in the whatsthis help + * \param index The position where to inserts the item. The item will be appended if index is negative. + * + * \return true if the item could be inserted. False if the value had already been inserted. + */ + bool insertItem( int value, const QString& text, const QString& description, int index = -1 ); + + void addGlobalWhatsThisText( const QString& top, const QString& bottom ); + + private slots: + void slotItemActivated( int ); + void slotItemHighlighted( int ); + + private: + void updateWhatsThis(); + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bintvalidator.cpp b/libk3b/tools/k3bintvalidator.cpp new file mode 100644 index 0000000..dabf719 --- /dev/null +++ b/libk3b/tools/k3bintvalidator.cpp @@ -0,0 +1,137 @@ +/* + * + * $Id: k3bintvalidator.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include +#include + +#include "k3bintvalidator.h" + +#include +#include +#include + + +K3bIntValidator::K3bIntValidator ( QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + m_min = m_max = 0; +} + + +K3bIntValidator::K3bIntValidator ( int bottom, int top, QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + m_min = bottom; + m_max = top; +} + + +K3bIntValidator::~K3bIntValidator () +{ +} + + +QValidator::State K3bIntValidator::validate ( QString &str, int & ) const +{ + bool ok; + int val = 0; + QString newStr; + + newStr = str.stripWhiteSpace(); + newStr = newStr.upper(); + + if( newStr.length() ) { + // check for < 0 + bool minus = newStr.startsWith( "-" ); + if( minus ) + newStr.remove( 0, 1 ); + + // check for hex + bool hex = newStr.startsWith( "0X" ); + + if( hex ) + newStr.remove( 0, 2 ); + + // a special case + if( newStr.isEmpty() ) { + if( minus && m_min && m_min >= 0) + ok = false; + else + return QValidator::Acceptable; + } + + val = newStr.toInt( &ok, hex ? 16 : 10 ); + if( minus ) + val *= -1; + } + else { + val = 0; + ok = true; + } + + if( !ok ) + return QValidator::Invalid; + + if( m_min && val > 0 && val < m_min ) + return QValidator::Acceptable; + + if( m_max && val < 0 && val > m_max ) + return QValidator::Acceptable; + + if( (m_max && val > m_max) || (m_min && val < m_min) ) + return QValidator::Invalid; + + return QValidator::Valid; +} + + +void K3bIntValidator::fixup ( QString& ) const +{ + // TODO: remove preceding zeros +} + + +void K3bIntValidator::setRange ( int bottom, int top ) +{ + m_min = bottom; + m_max = top; + + if( m_max < m_min ) + m_max = m_min; +} + + +int K3bIntValidator::bottom () const +{ + return m_min; +} + + +int K3bIntValidator::top () const +{ + return m_max; +} + + +int K3bIntValidator::toInt( const QString& s, bool* ok ) +{ + if( s.lower().startsWith( "0x" ) ) + return s.right( s.length()-2 ).toInt( ok, 16 ); + else if( s.lower().startsWith( "-0x" ) ) + return -1 * s.right( s.length()-3 ).toInt( ok, 16 ); + else + return s.toInt( ok, 10 ); +} diff --git a/libk3b/tools/k3bintvalidator.h b/libk3b/tools/k3bintvalidator.h new file mode 100644 index 0000000..551d56a --- /dev/null +++ b/libk3b/tools/k3bintvalidator.h @@ -0,0 +1,84 @@ +/* + * + * $Id: k3bintvalidator.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_INT_VALIDATOR_H_ +#define _K3B_INT_VALIDATOR_H_ + +#include +#include "k3b_export.h" +class QWidget; +class QString; + +/** + * QValidator for integers. + * + * It differs from QIntValidator and KIntValidator in the fact that + * it also accepts hex numbers prefixed with 0x. + */ +class LIBK3B_EXPORT K3bIntValidator : public QValidator +{ + public: + /** + * Constuctor. Also sets the base value. + */ + K3bIntValidator ( QWidget * parent, const char * name = 0 ); + + /** + * Constructor. Also sets the minimum, maximum, and numeric base values. + */ + K3bIntValidator ( int bottom, int top, QWidget * parent, const char * name = 0 ); + + /** + * Destructs the validator. + */ + virtual ~K3bIntValidator (); + + /** + * Validates the text, and return the result. Does not modify the parameters. + */ + virtual State validate ( QString &, int & ) const; + + /** + * Fixes the text if possible, providing a valid string. The parameter may be modified. + */ + virtual void fixup ( QString & ) const; + + /** + * Sets the minimum and maximum values allowed. + */ + virtual void setRange ( int bottom, int top ); + + /** + * Returns the current minimum value allowed. + */ + virtual int bottom () const; + + /** + * Returns the current maximum value allowed. + */ + virtual int top () const; + + /** + * If the string starts with 0x it's assumed to be a hex number. + */ + static int toInt( const QString&, bool* ok = 0 ); + + private: + int m_min; + int m_max; +}; + +#endif diff --git a/libk3b/tools/k3biso9660.cpp b/libk3b/tools/k3biso9660.cpp new file mode 100644 index 0000000..84edc4b --- /dev/null +++ b/libk3b/tools/k3biso9660.cpp @@ -0,0 +1,899 @@ +/* + * + * $Id: k3biso9660.cpp 690529 2007-07-21 10:51:47Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include +#include + +#include "k3biso9660.h" +#include "k3biso9660backend.h" + +#include + +#include "libisofs/isofs.h" + +#include +#include +#include +#include + +#include + + +/* callback function for libisofs */ +int K3bIso9660::read_callback( char* buf, sector_t start, int len, void* udata ) +{ + K3bIso9660* isoF = static_cast(udata); + + return isoF->read( start, buf, len ); +} + +/* callback function for libisofs */ +int K3bIso9660::isofs_callback( struct iso_directory_record *idr, void *udata ) +{ + K3bIso9660 *iso = static_cast (udata); + QString path, isoPath,user,group,symlink; + int i; + int access; + int time,cdate,adate; + rr_entry rr; + bool special=false; + K3bIso9660Entry *entry=0; + //K3bIso9660Entry *oldentry=0; + char z_algo[2],z_params[2]; + int z_size=0; + + if (isonum_711(idr->name_len)==1) { + switch (idr->name[0]) { + case 0: + path+=("."); + special=true; + break; + case 1: + path+=(".."); + special=true; + break; + } + } + // + // First extract the raw iso9660 name + // + if( !special ) { + for( i = 0; i < isonum_711( idr->name_len ); i++ ) { + if( idr->name[i] ) + isoPath += idr->name[i]; + } + } + else + isoPath = path; + + // + // Now see if we have RockRidge + // + if( !iso->plainIso9660() && ParseRR(idr,&rr) > 0 ) { + iso->m_rr = true; + if (!special) + path = QString::fromLocal8Bit( rr.name ); + symlink=rr.sl; + access=rr.mode; + time=0;//rr.st_mtime; + adate=0;//rr.st_atime; + cdate=0;//rr.st_ctime; + user.setNum(rr.uid); + group.setNum(rr.gid); + z_algo[0]=rr.z_algo[0];z_algo[1]=rr.z_algo[1]; + z_params[0]=rr.z_params[0];z_params[1]=rr.z_params[1]; + z_size=rr.z_size; + } + else { + access=iso->dirent->permissions() & ~S_IFMT; + adate=cdate=time=isodate_915(idr->date,0); + user=iso->dirent->user(); + group=iso->dirent->group(); + if (idr->flags[0] & 2) access |= S_IFDIR; else access |= S_IFREG; + if (!special) { + if( !iso->plainIso9660() && iso->jolietLevel() ) { + for (i=0;i<(isonum_711(idr->name_len)-1);i+=2) { + QChar ch( be2me_16(*((ushort*)&(idr->name[i]))) ); + if (ch==';') break; + path+=ch; + } + } + else { + // no RR, no Joliet, just plain iso9660 + path = isoPath; + + // remove the version field + int pos = path.find( ';' ); + if( pos > 0 ) + path.truncate( pos ); + } + if (path.endsWith(".")) path.setLength(path.length()-1); + } + } + + if( !iso->plainIso9660() ) + FreeRR(&rr); + + if (idr->flags[0] & 2) { + entry = new K3bIso9660Directory( iso, isoPath, path, access | S_IFDIR, time, adate, cdate, + user, group, symlink, + special ? 0 : isonum_733(idr->extent), + special ? 0 : isonum_733(idr->size) ); + } + else { + entry = new K3bIso9660File( iso, isoPath, path, access, time, adate, cdate, + user, group, symlink, isonum_733(idr->extent), isonum_733(idr->size) ); + if (z_size) + (static_cast(entry))->setZF( z_algo, z_params, z_size ); + } + iso->dirent->addEntry(entry); + + return 0; +} + + + +K3bIso9660Entry::K3bIso9660Entry( K3bIso9660* archive, + const QString& isoName, + const QString& name, + int access, + int date, + int adate, + int cdate, + const QString& user, + const QString& group, + const QString& symlink ) + : m_adate( adate ), + m_cdate( cdate ), + m_name( name ), + m_isoName( isoName ), + m_date( date ), + m_access( access ), + m_user( user ), + m_group( group ), + m_symlink( symlink ), + m_archive( archive ) +{ +} + + +K3bIso9660Entry::~K3bIso9660Entry() +{ +} + + + + + + +K3bIso9660File::K3bIso9660File( K3bIso9660* archive, + const QString& isoName, + const QString& name, + int access, + int date, + int adate, + int cdate, + const QString& user, + const QString& group, + const QString& symlink, + unsigned int pos, + unsigned int size ) + : K3bIso9660Entry( archive, isoName, name, access, date, adate, cdate, user, group, symlink ), + m_startSector(pos), + m_size(size) +{ + m_algo[0] = 0; + m_algo[1] = 0; + m_parms[0] = 0; + m_parms[1] = 0; + m_realsize = 0; +} + +K3bIso9660File::~K3bIso9660File() +{ +} + +void K3bIso9660File::setZF(char algo[2],char parms[2],int realsize) +{ + m_algo[0]=algo[0];m_algo[1]=algo[1]; + m_parms[0]=parms[0];m_parms[1]=parms[1]; + m_realsize=realsize; +} + + +int K3bIso9660File::read( unsigned int pos, char* data, int maxlen ) const +{ + if( pos >= size() ) + return 0; + + unsigned long startSec = m_startSector + pos/2048; + int startSecOffset = pos%2048; + char* buffer = data; + bool buffered = false; + unsigned long bufferLen = maxlen+startSecOffset; + + // cut to size + if( pos + maxlen > size() ) + bufferLen = size() - pos + startSecOffset; + + // pad to 2048 + if( bufferLen%2048 ) + bufferLen += (2048-(bufferLen%2048)); + + // we need to buffer if we changed the startSec or need a bigger buffer + if( startSecOffset || bufferLen > (unsigned int)maxlen ) { + buffered = true; + buffer = new char[bufferLen]; + } + + int read = archive()->read( startSec, buffer, bufferLen/2048 )*2048; + + if( buffered ) { + if( read > 0 ) { + // cut to requested data + read -= startSecOffset; + if( read + pos > size() ) + read = size() - pos; + if( read > maxlen ) + read = maxlen; + + ::memcpy( data, buffer+startSecOffset, read ); + } + delete [] buffer; + + return read; + } + else { + // cut read data + if( read + pos > size() ) + read = size() - pos; + + return read; + } +} + + +bool K3bIso9660File::copyTo( const QString& url ) const +{ + QFile of( url ); + if( of.open( IO_WriteOnly ) ) { + char buffer[2048*10]; + unsigned int pos = 0; + int r = 0; + while( ( r = read( pos, buffer, 2048*10 ) ) > 0 ) { + of.writeBlock( buffer, r ); + pos += r; + } + + return !r; + } + else { + kdDebug() << "(K3bIso9660File) could not open " << url << " for writing." << endl; + return false; + } +} + + +K3bIso9660Directory::K3bIso9660Directory( K3bIso9660* archive, + const QString& isoName, + const QString& name, + int access, + int date, + int adate, + int cdate, + const QString& user, + const QString& group, + const QString& symlink, + unsigned int pos, + unsigned int size ) + : K3bIso9660Entry( archive, isoName, name, access, date, adate, cdate, user, group, symlink ), + m_bExpanded( size == 0 ), // we can only expand entries that represent an actual directory + m_startSector(pos), + m_size(size) +{ + m_entries.setAutoDelete( true ); +} + +K3bIso9660Directory::~K3bIso9660Directory() +{ +} + + +void K3bIso9660Directory::expand() +{ + if( !m_bExpanded ) { + archive()->dirent = this; + if( ProcessDir( &K3bIso9660::read_callback, m_startSector, m_size, &K3bIso9660::isofs_callback, archive() ) ) + kdDebug() << "(K3bIso9660) failed to expand dir: " << name() << " with size: " << m_size << endl; + + m_bExpanded = true; + } +} + + +QStringList K3bIso9660Directory::entries() const +{ + // create a fake const method to fool the user ;) + const_cast(this)->expand(); + + QStringList l; + + QDictIterator it( m_entries ); + for( ; it.current(); ++it ) + l.append( it.currentKey() ); + + return l; +} + + +QStringList K3bIso9660Directory::iso9660Entries() const +{ + // create a fake const method to fool the user ;) + const_cast(this)->expand(); + + QStringList l; + + QDictIterator it( m_iso9660Entries ); + for( ; it.current(); ++it ) + l.append( it.currentKey() ); + + return l; +} + + +K3bIso9660Entry* K3bIso9660Directory::entry( const QString& n ) +{ + if( n.isEmpty() ) + return 0; + + expand(); + + QString name(n); + + // trailing slash ? -> remove + if( name.length() > 1 && name[name.length()-1] == '/' ) { + name.truncate( name.length()-1 ); + } + + int pos = name.find( '/' ); + while( pos == 0 ) { + if( name.length() > 1 ) { + name = name.mid( 1 ); // remove leading slash + pos = name.find( '/' ); // look again + } + else // "/" + return this; + } + + if ( pos != -1 ) { + QString left = name.left( pos ); + QString right = name.mid( pos + 1 ); + + K3bIso9660Entry* e = m_entries[ left ]; + if ( !e || !e->isDirectory() ) + return 0; + return static_cast(e)->entry( right ); + } + + return m_entries[ name ]; +} + + +K3bIso9660Entry* K3bIso9660Directory::iso9660Entry( const QString& n ) +{ + if( n.isEmpty() ) + return 0; + + expand(); + + QString name(n); + + // trailing slash ? -> remove + if( name.length() > 1 && name[name.length()-1] == '/' ) { + name.truncate( name.length()-1 ); + } + + int pos = name.find( '/' ); + while( pos == 0 ) { + if( name.length() > 1 ) { + name = name.mid( 1 ); // remove leading slash + pos = name.find( '/' ); // look again + } + else // "/" + return this; + } + + if ( pos != -1 ) { + QString left = name.left( pos ); + QString right = name.mid( pos + 1 ); + + K3bIso9660Entry* e = m_iso9660Entries[ left ]; + if ( !e || !e->isDirectory() ) + return 0; + return static_cast(e)->iso9660Entry( right ); + } + + return m_iso9660Entries[ name ]; +} + + +const K3bIso9660Entry* K3bIso9660Directory::entry( const QString& name ) const +{ + return const_cast(this)->entry( name ); +} + + +const K3bIso9660Entry* K3bIso9660Directory::iso9660Entry( const QString& name ) const +{ + return const_cast(this)->iso9660Entry( name ); +} + + +void K3bIso9660Directory::addEntry( K3bIso9660Entry* entry ) +{ + m_entries.insert( entry->name(), entry ); + m_iso9660Entries.insert( entry->isoName(), entry ); +} + + + + + +class K3bIso9660::Private +{ +public: + Private() + : cdDevice(0), + fd(-1), + isOpen(false), + startSector(0), + plainIso9660(false), + backend(0) { + } + + QPtrList elToritoDirs; + QPtrList jolietDirs; + QPtrList isoDirs; + QPtrList rrDirs; // RockRidge + + K3bIso9660SimplePrimaryDescriptor primaryDesc; + + K3bDevice::Device* cdDevice; + int fd; + + bool isOpen; + + // only used for direkt K3bDevice::Device access + unsigned int startSector; + + bool plainIso9660; + + K3bIso9660Backend* backend; +}; + + +K3bIso9660::K3bIso9660( const QString& filename ) + : m_filename( filename ) +{ + d = new Private(); +} + + +K3bIso9660::K3bIso9660( int fd ) +{ + d = new Private(); + d->fd = fd; +} + + +K3bIso9660::K3bIso9660( K3bIso9660Backend* backend ) +{ + d = new Private(); + d->backend = backend; +} + + +K3bIso9660::K3bIso9660( K3bDevice::Device* dev, unsigned int startSector ) +{ + d = new Private(); + d->cdDevice = dev; + d->startSector = startSector; +} + + +K3bIso9660::~K3bIso9660() +{ + close(); + delete d->backend; + delete d; +} + + +void K3bIso9660::setStartSector( unsigned int startSector ) +{ + d->startSector = startSector; +} + + +void K3bIso9660::setPlainIso9660( bool b ) +{ + d->plainIso9660 = b; +} + + +bool K3bIso9660::plainIso9660() const +{ + return d->plainIso9660; +} + + +int K3bIso9660::read( unsigned int sector, char* data, int count ) +{ + if( count == 0 ) + return 0; + else + return d->backend->read( sector, data, count ); +} + + +void K3bIso9660::addBoot(struct el_torito_boot_descriptor* bootdesc) +{ + int i,size; + boot_head boot; + boot_entry *be; + QString path; + K3bIso9660File *entry; + + entry=new K3bIso9660File( this, "Catalog", "Catalog", dirent->permissions() & ~S_IFDIR, + dirent->date(), dirent->adate(), dirent->cdate(), + dirent->user(), dirent->group(), QString::null, + isonum_731(bootdesc->boot_catalog), 2048 ); + dirent->addEntry(entry); + if (!ReadBootTable(&K3bIso9660::read_callback,isonum_731(bootdesc->boot_catalog),&boot,this)) { + i=1; + be=boot.defentry; + while (be) { + size=BootImageSize(&K3bIso9660::read_callback, + isonum_711(((struct default_entry*) be->data)->media), + isonum_731(((struct default_entry*) be->data)->start), + isonum_721(((struct default_entry*) be->data)->seccount), + this); + path="Default Image"; + if (i>1) path += " (" + QString::number(i) + ")"; + entry=new K3bIso9660File( this, path, path, dirent->permissions() & ~S_IFDIR, + dirent->date(), dirent->adate(), dirent->cdate(), + dirent->user(), dirent->group(), QString::null, + isonum_731(((struct default_entry*) be->data)->start), size<<9 ); + dirent->addEntry(entry); + be=be->next; + i++; + } + + FreeBootTable(&boot); + } +} + + +bool K3bIso9660::open() +{ + if( d->isOpen ) + return true; + + if( !d->backend ) { + // create a backend + + if( !m_filename.isEmpty() ) + d->backend = new K3bIso9660FileBackend( m_filename ); + + else if( d->fd > 0 ) + d->backend = new K3bIso9660FileBackend( d->fd ); + + else if( d->cdDevice ) { + // now check if we have a scrambled video dvd + if( d->cdDevice->copyrightProtectionSystemType() == 1 ) { + + kdDebug() << "(K3bIso9660) found encrypted dvd. using libdvdcss." << endl; + + // open the libdvdcss stuff + d->backend = new K3bIso9660LibDvdCssBackend( d->cdDevice ); + if( !d->backend->open() ) { + // fallback to devicebackend + delete d->backend; + d->backend = new K3bIso9660DeviceBackend( d->cdDevice ); + } + } + else + d->backend = new K3bIso9660DeviceBackend( d->cdDevice ); + } + } + + d->isOpen = d->backend->open(); + if( !d->isOpen ) + return false; + + iso_vol_desc *desc; + QString path,tmp,uid,gid; + k3b_struct_stat buf; + int access,c_i,c_j; + struct el_torito_boot_descriptor* bootdesc; + + + /* We'll use the permission and user/group of the 'host' file except + * in Rock Ridge, where the permissions are stored on the file system + */ + if ( k3b_stat( QFile::encodeName(m_filename), &buf ) < 0 ) { + /* defaults, if stat fails */ + memset(&buf,0,sizeof(k3b_struct_stat)); + buf.st_mode=0777; + } + uid.setNum(buf.st_uid); + gid.setNum(buf.st_gid); + access = buf.st_mode & ~S_IFMT; + + + int c_b=1; + c_i=1;c_j=1; + + desc = ReadISO9660( &K3bIso9660::read_callback, d->startSector, this ); + + if (!desc) { + kdDebug() << "K3bIso9660::openArchive no volume descriptors" << endl; + close(); + return false; + } + + while (desc) { + + m_rr = false; + + switch (isonum_711(desc->data.type)) { + case ISO_VD_BOOT: + + bootdesc=(struct el_torito_boot_descriptor*) &(desc->data); + if( !memcmp( EL_TORITO_ID, bootdesc->system_id, ISODCL(8,39) ) ) { + path="El Torito Boot"; + if( c_b > 1 ) + path += " (" + QString::number(c_b) + ")"; + + dirent = new K3bIso9660Directory( this, path, path, access | S_IFDIR, + buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, QString::null ); + d->elToritoDirs.append( dirent ); + + addBoot(bootdesc); + c_b++; + } + break; + + case ISO_VD_PRIMARY: + createSimplePrimaryDesc( (struct iso_primary_descriptor*)&desc->data ); + // fall through + case ISO_VD_SUPPLEMENTARY: + { + struct iso_primary_descriptor* primaryDesc = (struct iso_primary_descriptor*)&desc->data; + struct iso_directory_record* idr = (struct iso_directory_record*)&primaryDesc->root_directory_record; + + m_joliet = JolietLevel(&desc->data); + + // skip joliet in plain iso mode + if( m_joliet && plainIso9660() ) + break; + + if (m_joliet) { + path = "Joliet level " + QString::number(m_joliet); + if( c_j > 1 ) + path += " (" + QString::number(c_j) + ")"; + } + else { + path = QString::fromLocal8Bit( primaryDesc->volume_id, 32 ); + if( c_i > 1 ) + path += " (" + QString::number(c_i) + ")"; + } + + dirent = new K3bIso9660Directory( this, path, path, access | S_IFDIR, + buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, QString::null ); + + // expand the root entry + ProcessDir( &K3bIso9660::read_callback, isonum_733(idr->extent),isonum_733(idr->size),&K3bIso9660::isofs_callback,this); + + if (m_joliet) + c_j++; + else + c_i++; + + if( m_joliet ) + d->jolietDirs.append( dirent ); + else { + if( m_rr ) + d->rrDirs.append( dirent ); + d->isoDirs.append( dirent ); + } + + break; + } + } + desc = desc->next; + } + + FreeISO9660(desc); + + return true; +} + + +bool K3bIso9660::isOpen() const +{ + return d->isOpen; +} + + +void K3bIso9660::createSimplePrimaryDesc( struct iso_primary_descriptor* desc ) +{ + d->primaryDesc.volumeId = QString::fromLocal8Bit( desc->volume_id, 32 ).stripWhiteSpace(); + d->primaryDesc.systemId = QString::fromLocal8Bit( desc->system_id, 32 ).stripWhiteSpace(); + d->primaryDesc.volumeSetId = QString::fromLocal8Bit( desc->volume_set_id, 128 ).stripWhiteSpace(); + d->primaryDesc.publisherId = QString::fromLocal8Bit( desc->publisher_id, 128 ).stripWhiteSpace(); + d->primaryDesc.preparerId = QString::fromLocal8Bit( desc->preparer_id, 128 ).stripWhiteSpace(); + d->primaryDesc.applicationId = QString::fromLocal8Bit( desc->application_id, 128 ).stripWhiteSpace(); + d->primaryDesc.volumeSetSize = isonum_723(desc->volume_set_size); + d->primaryDesc.volumeSetNumber = isonum_723(desc->volume_set_size); + d->primaryDesc.logicalBlockSize = isonum_723(desc->logical_block_size); + d->primaryDesc.volumeSpaceSize = isonum_733(desc->volume_space_size); +} + + +void K3bIso9660::close() +{ + if( d->isOpen ) { + d->backend->close(); + + // Since the first isoDir is the KArchive + // root we must not delete it but all the + // others. + + d->elToritoDirs.setAutoDelete(true); + d->jolietDirs.setAutoDelete(true); + d->isoDirs.setAutoDelete(true); + d->elToritoDirs.clear(); + d->jolietDirs.clear(); + d->isoDirs.clear(); + + d->isOpen = false; + } +} + + +const K3bIso9660Directory* K3bIso9660::firstJolietDirEntry() const +{ + return d->jolietDirs.first(); +} + + +const K3bIso9660Directory* K3bIso9660::firstIsoDirEntry() const +{ + return d->isoDirs.first(); +} + + +const K3bIso9660Directory* K3bIso9660::firstElToritoEntry() const +{ + return d->elToritoDirs.first(); +} + + +const K3bIso9660Directory* K3bIso9660::firstRRDirEntry() const +{ + return d->rrDirs.first(); +} + + +const K3bIso9660SimplePrimaryDescriptor& K3bIso9660::primaryDescriptor() const +{ + return d->primaryDesc; +} + + +void K3bIso9660::debug() const +{ + if( isOpen() ) { + kdDebug() << "System Id: " << primaryDescriptor().systemId << endl; + kdDebug() << "Volume Id: " << primaryDescriptor().volumeId << endl; + kdDebug() << "Volume Set Id: " << primaryDescriptor().volumeSetId << endl; + kdDebug() << "Preparer Id: " << primaryDescriptor().preparerId << endl; + kdDebug() << "Publisher Id: " << primaryDescriptor().publisherId << endl; + kdDebug() << "Application Id: " << primaryDescriptor().applicationId << endl; + kdDebug() << "Volume Set Size: " << primaryDescriptor().volumeSetSize << endl; + kdDebug() << "Volume Set Number: " << primaryDescriptor().volumeSetNumber << endl; + + if( firstIsoDirEntry() ) { + kdDebug() << "First ISO Dir entry:" << endl; + kdDebug() << "----------------------------------------------" << endl; + debugEntry( firstIsoDirEntry(), 0 ); + kdDebug() << "----------------------------------------------" << endl << endl; + } + if( firstRRDirEntry() ) { + kdDebug() << "First RR Dir entry:" << endl; + kdDebug() << "----------------------------------------------" << endl; + debugEntry( firstRRDirEntry(), 0 ); + kdDebug() << "----------------------------------------------" << endl << endl; + } + if( firstJolietDirEntry() ) { + kdDebug() << "First Joliet Dir entry:" << endl; + kdDebug() << "----------------------------------------------" << endl; + debugEntry( firstJolietDirEntry(), 0 ); + kdDebug() << "----------------------------------------------" << endl << endl; + } + } +} + + +void K3bIso9660::debugEntry( const K3bIso9660Entry* entry, int depth ) const +{ + if( !entry ) { + kdDebug() << "(K3bIso9660::debugEntry) null entry." << endl; + return; + } + + QString spacer; + spacer.fill( ' ', depth*3 ); + kdDebug() << spacer << "- " << entry->name() << " (" << entry->isoName() << ")" << endl; + if( entry->isDirectory() ) { + const K3bIso9660Directory* dir = dynamic_cast(entry); + QStringList entries = dir->entries(); + for( QStringList::const_iterator it = entries.begin(); it != entries.end(); ++it ) { + debugEntry( dir->entry( *it ), depth+1 ); + } + } +} + + +K3bIso9660SimplePrimaryDescriptor::K3bIso9660SimplePrimaryDescriptor() + : volumeSetSize(0), + volumeSetNumber(0), + logicalBlockSize(0), + volumeSpaceSize(0) +{ +} + + +bool operator==( const K3bIso9660SimplePrimaryDescriptor& d1, + const K3bIso9660SimplePrimaryDescriptor& d2 ) +{ + return( d1.volumeId == d2.volumeId && + d1.systemId == d2.systemId && + d1.volumeSetId == d2.volumeSetId && + d1.publisherId == d2.publisherId && + d1.preparerId == d2.preparerId && + d1.applicationId == d2.applicationId && + d1.volumeSetSize == d2.volumeSetSize && + d1.volumeSetNumber == d2.volumeSetNumber && + d1.logicalBlockSize == d2.logicalBlockSize && + d1.volumeSpaceSize == d2.volumeSpaceSize ); +} + + +bool operator!=( const K3bIso9660SimplePrimaryDescriptor& d1, + const K3bIso9660SimplePrimaryDescriptor& d2 ) +{ + return( d1.volumeId != d2.volumeId || + d1.systemId != d2.systemId || + d1.volumeSetId != d2.volumeSetId || + d1.publisherId != d2.publisherId || + d1.preparerId != d2.preparerId || + d1.applicationId != d2.applicationId || + d1.volumeSetSize != d2.volumeSetSize || + d1.volumeSetNumber != d2.volumeSetNumber || + d1.logicalBlockSize != d2.logicalBlockSize || + d1.volumeSpaceSize != d2.volumeSpaceSize ); +} diff --git a/libk3b/tools/k3biso9660.h b/libk3b/tools/k3biso9660.h new file mode 100644 index 0000000..7fc52d9 --- /dev/null +++ b/libk3b/tools/k3biso9660.h @@ -0,0 +1,453 @@ +/* + * + * $Id: k3biso9660.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_ISO9660_H_ +#define _K3B_ISO9660_H_ + +#include +#include + +#include +#include +#include +#include + +#include "k3b_export.h" + + +namespace K3bDevice { + class Device; +} + +class K3bIso9660; +class K3bIso9660Backend; +struct iso_directory_record; +struct el_torito_boot_descriptor; +struct iso_primary_descriptor; + +typedef long sector_t; + + + +/** + * Simplyfied primary descriptor which just contains the fields + * used by K3b. + */ +class LIBK3B_EXPORT K3bIso9660SimplePrimaryDescriptor +{ + public: + /** + * Creates an empty descriptor + */ + K3bIso9660SimplePrimaryDescriptor(); + + QString volumeId; + QString systemId; + QString volumeSetId; + QString publisherId; + QString preparerId; + QString applicationId; + int volumeSetSize; + int volumeSetNumber; + long logicalBlockSize; + long long volumeSpaceSize; +}; + + +LIBK3B_EXPORT bool operator==( const K3bIso9660SimplePrimaryDescriptor& d1, + const K3bIso9660SimplePrimaryDescriptor& d2 ); +LIBK3B_EXPORT bool operator!=( const K3bIso9660SimplePrimaryDescriptor& d1, + const K3bIso9660SimplePrimaryDescriptor& d2 ); + + +/** + * Base class for all entries in a K3bIso9660 archive. A lot has been copied + * from KArchive. + */ +class LIBK3B_EXPORT K3bIso9660Entry +{ + public: + K3bIso9660Entry( K3bIso9660* archive, + const QString& isoName, + const QString& name, + int access, + int date, + int adate, + int cdate, + const QString& user, + const QString& group, + const QString& symlink ); + virtual ~K3bIso9660Entry(); + + int adate() const { return m_adate; } + int cdate() const { return m_cdate; } + + /** + * Creation date of the file. + * @return the creation date + */ + QDateTime datetime() const; + + /** + * Creation date of the file. + * @return the creation date in seconds since 1970 + */ + int date() const { return m_date; } + + /** + * Name of the file without path. + * @return The file name without path. + */ + const QString& name() const { return m_name; } + + /** + * \return The raw name as saved in the ISO9660 tree + */ + const QString& isoName() const { return m_isoName; } + + /** + * The permissions and mode flags as returned by the stat() function + * in st_mode. + * @return the permissions + */ + mode_t permissions() const { return m_access; } + + /** + * User who created the file. + * @return the owner of the file + */ + const QString& user() const { return m_user; } + + /** + * Group of the user who created the file. + * @return the group of the file + */ + const QString& group() const { return m_group; } + + /** + * Symlink if there is one. + * @return the symlink, or QString::null + */ + const QString& symlink() const { return m_symlink; } + + /** + * Checks whether the entry is a file. + * @return true if this entry is a file + */ + virtual bool isFile() const { return false; } + + /** + * Checks whether the entry is a directory. + * @return true if this entry is a directory + */ + virtual bool isDirectory() const { return false; } + + K3bIso9660* archive() const { return m_archive; } + + private: + int m_adate; + int m_cdate; + QString m_name; + QString m_isoName; + int m_date; + mode_t m_access; + QString m_user; + QString m_group; + QString m_symlink; + K3bIso9660* m_archive; +}; + + +class LIBK3B_EXPORT K3bIso9660Directory : public K3bIso9660Entry +{ + public: + K3bIso9660Directory( K3bIso9660* archive, + const QString& isoName, + const QString& name, + int access, + int date, + int adate, + int cdate, + const QString& user, + const QString& group, + const QString& symlink, + unsigned int pos = 0, + unsigned int size = 0 ); + ~K3bIso9660Directory(); + + /** + * Returns a list of sub-entries. + * @return the names of all entries in this directory (filenames, no path). + */ + QStringList entries() const; + + /** + * Returns the entry with the given name. + * @param name may be "test1", "mydir/test3", "mydir/mysubdir/test3", etc. + * @return a pointer to the entry in the directory. + */ + K3bIso9660Entry* entry( const QString& name ); + + /** + * Returns the entry with the given name. + * @param name may be "test1", "mydir/test3", "mydir/mysubdir/test3", etc. + * @return a pointer to the entry in the directory. + */ + const K3bIso9660Entry* entry( const QString& name ) const; + + /** + * Returns a list of sub-entries. + * Searches for Iso9660 names. + * @return the names of all entries in this directory (filenames, no path). + */ + QStringList iso9660Entries() const; + + /** + * Returns the entry with the given name. + * Searches for Iso9660 names. + * @param name may be "test1", "mydir/test3", "mydir/mysubdir/test3", etc. + * @return a pointer to the entry in the directory. + */ + K3bIso9660Entry* iso9660Entry( const QString& name ); + + /** + * Returns the entry with the given name. + * Searches for Iso9660 names. + * @param name may be "test1", "mydir/test3", "mydir/mysubdir/test3", etc. + * @return a pointer to the entry in the directory. + */ + const K3bIso9660Entry* iso9660Entry( const QString& name ) const; + + /** + * @internal + * Adds a new entry to the directory. + */ + void addEntry( K3bIso9660Entry* ); + + /** + * Checks whether this entry is a directory. + * @return true, since this entry is a directory + */ + bool isDirectory() const { return true; } + + private: + void expand(); + + QDict m_entries; + QDict m_iso9660Entries; + + bool m_bExpanded; + unsigned int m_startSector; + unsigned int m_size; +}; + + +class LIBK3B_EXPORT K3bIso9660File : public K3bIso9660Entry +{ + public: + /** + * @param pos start sector + */ + K3bIso9660File( K3bIso9660* archive, + const QString& isoName, + const QString& name, + int access, + int date, + int adate, + int cdate, + const QString& user, + const QString& group, + const QString& symlink, + unsigned int pos, + unsigned int size ); + ~K3bIso9660File(); + + bool isFile() const { return true; } + + void setZF( char algo[2], char parms[2], int realsize ); + int realsize() const { return m_realsize; } + + /** + * @return size in bytes. + */ + unsigned int size() const { return m_size; } + + /** + * Returnes the startSector of the file. + */ + unsigned int startSector() const { return m_startSector; } + + /** + * Returnes the startOffset of the file in bytes. + */ + unsigned long long startPostion() const { return (unsigned long long)m_startSector * 2048; } + + /** + * @param pos offset in bytes + * @param len max number of bytes to read + */ + int read( unsigned int pos, char* data, int len ) const; + + /** + * Copy this file to a url. + */ + bool copyTo( const QString& url ) const; + + private: + char m_algo[2]; + char m_parms[2]; + int m_realsize; + + unsigned int m_curpos; + unsigned int m_startSector; + unsigned int m_size; +}; + + +/** + * This class is based on the KIso class by + * Gy�gy Szombathelyi . + * A lot has been changed and bugfixed. + * The API has been improved to be useful. + * + * Due to the stupid Qt which does not support large files as default + * we cannot use QIODevice with DVDs! That's why we have our own + * reading code which is not allowed by KArchive (which is limited to int + * by the way... who the hell designed this?) + * I also removed the KArchive inheritance because of the named reasons. + * So this stuff contains a lot KArchive code which has been made usable. + * + * That does not mean that this class is well designed. No, it's not. :) + * + * Opening a K3bIso9660 object should be fast since creation of the directory + * and file entries is not done until a call to K3bIso9660Directory::entries. +*/ +class LIBK3B_EXPORT K3bIso9660 +{ + public: + /** + * Creates an instance that operates on the given filename. + * using the compression filter associated to given mimetype. + * + * @param filename is a local path (e.g. "/home/weis/myfile.tgz") + */ + K3bIso9660( const QString& filename ); + + /** + * Special case which always reads the TOC from the specified sector + * thus supporting multisession CDs. + */ + K3bIso9660( K3bDevice::Device* dev, unsigned int startSector = 0 ); + + /** + * @param fd open file descriptor + */ + K3bIso9660( int fd ); + + /** + * Directly specify the backend to read from. + * K3bIso9660 will take ownership of the backend and delete it. + */ + K3bIso9660( K3bIso9660Backend* ); + + /** + * If the .iso is still opened, then it will be + * closed automatically by the destructor. + */ + virtual ~K3bIso9660(); + + /** + * Set where to start reading in the source. + */ + void setStartSector( unsigned int startSector ); + + /** + * If set to true before opening K3bIso9660 will ignore RR and joliet extensions + * and only create plain iso9660 names. + */ + void setPlainIso9660( bool ); + + bool plainIso9660() const; + + /** + * Opens the archive for reading. + * Parses the directory listing of the archive + * and creates the K3bIso9660Directory/K3bIso9660File entries. + */ + bool open(); + + bool isOpen() const; + + /** + * Closes everything. + * This is also called in the destructor + */ + void close(); + + /** + * @param sector startsector + * @param len number of sectors + * @return number of sectors read or -1 on error + */ + int read( unsigned int sector, char* data, int len ); + + /** + * The name of the os file, as passed to the constructor + * Null if you did not use the QString constructor. + */ + const QString& fileName() { return m_filename; } + + const K3bIso9660Directory* firstJolietDirEntry() const; + const K3bIso9660Directory* firstRRDirEntry() const; + const K3bIso9660Directory* firstIsoDirEntry() const; + const K3bIso9660Directory* firstElToritoEntry() const; + + /** + * @returns 0 if no joliet desc could be found + * the joliet level (1-3) otherwise + */ + int jolietLevel() const { return m_joliet; } + + const K3bIso9660SimplePrimaryDescriptor& primaryDescriptor() const; + + void debug() const; + + private: + /** + * @internal + */ + void addBoot( struct el_torito_boot_descriptor* bootdesc ); + void createSimplePrimaryDesc( struct iso_primary_descriptor* desc ); + + void debugEntry( const K3bIso9660Entry*, int depth ) const; + + int m_joliet; + + // only used for creation + static int read_callback( char* buf, sector_t start, int len, void* udata ); + static int isofs_callback( struct iso_directory_record* idr, void *udata ); + K3bIso9660Directory *dirent; + bool m_rr; + friend class K3bIso9660Directory; + + private: + QString m_filename; + + class Private; + Private * d; +}; + +#endif diff --git a/libk3b/tools/k3biso9660backend.cpp b/libk3b/tools/k3biso9660backend.cpp new file mode 100644 index 0000000..aacc079 --- /dev/null +++ b/libk3b/tools/k3biso9660backend.cpp @@ -0,0 +1,239 @@ +/* + * + * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3biso9660backend.h" +#include "k3blibdvdcss.h" + +#include +#include +#include +#include + +#include + +#include + + +// +// K3bIso9660DeviceBackend ----------------------------------- +// + +K3bIso9660DeviceBackend::K3bIso9660DeviceBackend( K3bDevice::Device* dev ) + : m_device( dev ), + m_isOpen(false) +{ +} + + +K3bIso9660DeviceBackend::~K3bIso9660DeviceBackend() +{ + close(); +} + + +bool K3bIso9660DeviceBackend::open() +{ + if( m_isOpen ) + return true; + else if( m_device->open() ) { + // set optimal reading speed + m_device->setSpeed( 0xffff, 0xffff ); + m_isOpen = true; + return true; + } + else + return false; +} + + +void K3bIso9660DeviceBackend::close() +{ + if( m_isOpen ) { + m_isOpen = false; + m_device->close(); + } +} + + +int K3bIso9660DeviceBackend::read( unsigned int sector, char* data, int len ) +{ + if( isOpen() ) { + // + // split the number of sectors to be read + // FIXME: use a "real" value, not some arbitrary one + // + static const int maxReadSectors = 20; + int sectorsRead = 0; + int retries = 10; // TODO: no fixed value + while( retries ) { + int read = QMIN(len-sectorsRead, maxReadSectors); + if( !m_device->read10( (unsigned char*)(data+sectorsRead*2048), + read*2048, + sector+sectorsRead, + read ) ) { + retries--; + } + else { + sectorsRead += read; + retries = 10; // new retires for every read part + if( sectorsRead == len ) + return len; + } + } + } + + return -1; +} + + +// +// K3bIso9660FileBackend ----------------------------------- +// + +K3bIso9660FileBackend::K3bIso9660FileBackend( const QString& filename ) + : m_filename( filename ), + m_fd( -1 ), + m_closeFd( true ) +{ +} + + +K3bIso9660FileBackend::K3bIso9660FileBackend( int fd ) + : m_fd( fd ), + m_closeFd( false ) +{ +} + + +K3bIso9660FileBackend::~K3bIso9660FileBackend() +{ + close(); +} + + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + +bool K3bIso9660FileBackend::open() +{ + if( m_fd > 0 ) + return true; + else { + m_fd = ::open( QFile::encodeName( m_filename ), O_RDONLY|O_LARGEFILE ); + return ( m_fd > 0 ); + } +} + + +void K3bIso9660FileBackend::close() +{ + if( m_closeFd && m_fd > 0 ) { + ::close( m_fd ); + m_fd = -1; + } +} + + + +bool K3bIso9660FileBackend::isOpen() const +{ + return ( m_fd > 0 ); +} + + +int K3bIso9660FileBackend::read( unsigned int sector, char* data, int len ) +{ + int read = 0; + if( ::lseek( m_fd, static_cast(sector)*2048, SEEK_SET ) != -1 ) + if( (read = ::read( m_fd, data, len*2048 )) != -1 ) + return read / 2048; + + return -1; +} + + + +// +// K3bIso9660LibDvdCssBackend ----------------------------------- +// + +K3bIso9660LibDvdCssBackend::K3bIso9660LibDvdCssBackend( K3bDevice::Device* dev ) + : m_device( dev ), + m_libDvdCss( 0 ) +{ +} + + +K3bIso9660LibDvdCssBackend::~K3bIso9660LibDvdCssBackend() +{ + close(); +} + + +bool K3bIso9660LibDvdCssBackend::open() +{ + if( !m_libDvdCss ) { + // open the libdvdcss stuff + m_libDvdCss = K3bLibDvdCss::create(); + + if( m_libDvdCss ) { + + if( !m_libDvdCss->open( m_device ) || + !m_libDvdCss->crackAllKeys() ) { + kdDebug() << "(K3bIso9660LibDvdCssBackend) Failed to retrieve all CSS keys." << endl; + close(); + } + } + else + kdDebug() << "(K3bIso9660LibDvdCssBackend) failed to open libdvdcss." << endl; + } + + return ( m_libDvdCss != 0 ); +} + + +void K3bIso9660LibDvdCssBackend::close() +{ + delete m_libDvdCss; + m_libDvdCss = 0; +} + + + +bool K3bIso9660LibDvdCssBackend::isOpen() const +{ + return ( m_libDvdCss != 0 ); +} + + +int K3bIso9660LibDvdCssBackend::read( unsigned int sector, char* data, int len ) +{ + int read = -1; + + if( isOpen() ) { + int retries = 10; // TODO: no fixed value + while( retries && !m_libDvdCss->readWrapped( reinterpret_cast(data), + sector, + len ) ) + retries--; + + if( retries > 0 ) + read = len; + } + + return read; +} + diff --git a/libk3b/tools/k3biso9660backend.h b/libk3b/tools/k3biso9660backend.h new file mode 100644 index 0000000..78937e5 --- /dev/null +++ b/libk3b/tools/k3biso9660backend.h @@ -0,0 +1,95 @@ +/* + * + * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_ISO9660_BACKEND_H_ +#define _K3B_ISO9660_BACKEND_H_ + +#include + +#include "k3b_export.h" + +namespace K3bDevice { + class Device; +} + +class K3bLibDvdCss; + + +class K3bIso9660Backend +{ + public: + K3bIso9660Backend() {} + virtual ~K3bIso9660Backend() {} + + virtual bool open() = 0; + virtual void close() = 0; + virtual bool isOpen() const = 0; + virtual int read( unsigned int sector, char* data, int len ) = 0; +}; + + +class K3bIso9660DeviceBackend : public K3bIso9660Backend +{ + public: + LIBK3B_EXPORT K3bIso9660DeviceBackend( K3bDevice::Device* dev ); + ~K3bIso9660DeviceBackend(); + + bool open(); + void close(); + bool isOpen() const { return m_isOpen; } + int read( unsigned int sector, char* data, int len ); + + private: + K3bDevice::Device* m_device; + bool m_isOpen; +}; + + +class K3bIso9660FileBackend : public K3bIso9660Backend +{ + public: + LIBK3B_EXPORT K3bIso9660FileBackend( const QString& filename ); + K3bIso9660FileBackend( int fd ); + ~K3bIso9660FileBackend(); + + bool open(); + void close(); + bool isOpen() const; + int read( unsigned int sector, char* data, int len ); + + private: + QString m_filename; + int m_fd; + bool m_closeFd; +}; + + +class K3bIso9660LibDvdCssBackend : public K3bIso9660Backend +{ + public: + LIBK3B_EXPORT K3bIso9660LibDvdCssBackend( K3bDevice::Device* ); + ~K3bIso9660LibDvdCssBackend(); + + bool open(); + void close(); + bool isOpen() const; + int read( unsigned int sector, char* data, int len ); + + private: + K3bDevice::Device* m_device; + K3bLibDvdCss* m_libDvdCss; +}; + +#endif diff --git a/libk3b/tools/k3blibdvdcss.cpp b/libk3b/tools/k3blibdvdcss.cpp new file mode 100644 index 0000000..0a8d1f0 --- /dev/null +++ b/libk3b/tools/k3blibdvdcss.cpp @@ -0,0 +1,307 @@ +/* + * + * $Id: k3blibdvdcss.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include + +#include "k3blibdvdcss.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include + + +void* K3bLibDvdCss::s_libDvdCss = 0; +int K3bLibDvdCss::s_counter = 0; + + +extern "C" { + struct dvdcss_s; + typedef struct dvdcss_s* dvdcss_t; + + dvdcss_t (*k3b_dvdcss_open)(char*); + int (*k3b_dvdcss_close)( dvdcss_t ); + int (*k3b_dvdcss_seek)( dvdcss_t, int, int ); + int (*k3b_dvdcss_read)( dvdcss_t, void*, int, int ); +} + + + +class K3bLibDvdCss::Private +{ +public: + Private() + :dvd(0) { + } + + dvdcss_t dvd; + K3bDevice::Device* device; + QValueVector< QPair > titleOffsets; + int currentSector; + bool currentSectorInTitle; +}; + +K3bLibDvdCss::K3bLibDvdCss() +{ + d = new Private(); + s_counter++; +} + + +K3bLibDvdCss::~K3bLibDvdCss() +{ + close(); + delete d; + s_counter--; + if( s_counter == 0 ) { + dlclose( s_libDvdCss ); + s_libDvdCss = 0; + } +} + + +bool K3bLibDvdCss::open( K3bDevice::Device* dev ) +{ + d->device = dev; + dev->close(); + d->dvd = k3b_dvdcss_open( const_cast( QFile::encodeName(dev->blockDeviceName()).data() ) ); + d->currentSector = 0; + d->currentSectorInTitle = false; + return ( d->dvd != 0 ); +} + + +void K3bLibDvdCss::close() +{ + if( d->dvd ) + k3b_dvdcss_close( d->dvd ); + d->dvd = 0; +} + + +int K3bLibDvdCss::seek( int sector, int flags ) +{ + return k3b_dvdcss_seek( d->dvd, sector, flags ); +} + + +int K3bLibDvdCss::read( void* buffer, int sectors, int flags ) +{ + return k3b_dvdcss_read( d->dvd, buffer, sectors, flags ); +} + + +int K3bLibDvdCss::readWrapped( void* buffer, int firstSector, int sectors ) +{ + // 1. are we in a title? + // 2. does a new title start in the read sector area? + // - see below, set title if firstSector is the first sector of a new title + // 3. does a title end in the read sector area? + // 3.1 does a previous title end + // 3.2 does the title from 2. already end + + // we need to seek to the first sector. Otherwise we get faulty data. + bool needToSeek = ( firstSector != d->currentSector || firstSector == 0 ); + bool inTitle = false; + bool startOfTitle = false; + + // + // Make sure we never read encrypted and unencrypted data at once since libdvdcss + // only decrypts the whole area of read sectors or nothing at all. + // + for( unsigned int i = 0; i < d->titleOffsets.count(); ++i ) { + int titleStart = d->titleOffsets[i].first; + int titleEnd = titleStart + d->titleOffsets[i].second - 1; + + // update key when entrering a new title + // FIXME: we also need this if we seek into a new title (not only the start of the title) + if( titleStart == firstSector ) + startOfTitle = needToSeek = inTitle = true; + + // check if a new title or non-title area starts inside the read sector range + if( firstSector < titleStart && firstSector+sectors > titleStart ) { + kdDebug() << "(K3bLibDvdCss) title start inside of sector range (" + << firstSector << "-" << (firstSector+sectors-1) + << "). only reading " << (titleStart - firstSector) << " sectors up to title offset " + << (titleStart-1) << endl; + sectors = titleStart - firstSector; + } + + if( firstSector < titleEnd && firstSector+sectors > titleEnd ) { + kdDebug() << "(K3bLibDvdCss) title end inside of sector range (" + << firstSector << "-" << (firstSector+sectors-1) + << "). only reading " << (titleEnd - firstSector + 1) << " sectors up to title offset " + << titleEnd << endl; + sectors = titleEnd - firstSector + 1; + inTitle = true; + } + + // is our read range part of one title + if( firstSector >= titleStart && firstSector+sectors-1 <= titleEnd ) + inTitle = true; + } + + if( needToSeek ) { + int flags = DVDCSS_NOFLAGS; + if( startOfTitle ) + flags = DVDCSS_SEEK_KEY; + else if( inTitle ) + flags = DVDCSS_SEEK_MPEG; + + kdDebug() << "(K3bLibDvdCss) need to seek from " << d->currentSector << " to " << firstSector << " with " << flags << endl; + + d->currentSector = seek( firstSector, flags ); + if( d->currentSector != firstSector ) { + kdDebug() << "(K3bLibDvdCss) seek failed: " << d->currentSector << endl; + return -1; + } + + kdDebug() << "(K3bLibDvdCss) seek done: " << d->currentSector << endl; + } + + + int flags = DVDCSS_NOFLAGS; + if( inTitle ) + flags = DVDCSS_READ_DECRYPT; + + int ret = read( buffer, sectors, flags ); + if( ret >= 0 ) + d->currentSector += ret; + else + d->currentSector = 0; // force a seek the next time + + return ret; +} + + +bool K3bLibDvdCss::crackAllKeys() +{ + // + // Loop over all titles and crack the keys (inspired by libdvdread) + // + kdDebug() << "(K3bLibDvdCss) cracking all keys." << endl; + + d->titleOffsets.clear(); + + K3bIso9660 iso( new K3bIso9660DeviceBackend( d->device ) ); + iso.setPlainIso9660( true ); + if( !iso.open() ) { + kdDebug() << "(K3bLibDvdCss) could not open iso9660 fs." << endl; + return false; + } + +#ifdef K3B_DEBUG + iso.debug(); +#endif + + const K3bIso9660Directory* dir = iso.firstIsoDirEntry(); + + int title = 0; + for( ; title < 100; ++title ) { + QString filename; + + // first we get the menu vob + if( title == 0 ) + filename.sprintf( "VIDEO_TS/VIDEO_TS.VOB" ); + else + filename.sprintf( "VIDEO_TS/VTS_%02d_%d.VOB", title, 0 ); + + const K3bIso9660File* file = dynamic_cast( dir->entry( filename ) ); + if( file && file->size() > 0 ) { + d->titleOffsets.append( qMakePair( (int)file->startSector(), (int)(file->size() / 2048U) ) ); + kdDebug() << "(K3bLibDvdCss) Get key for /" << filename << " at " << file->startSector() << endl; + if( seek( (int)file->startSector(), DVDCSS_SEEK_KEY ) < 0 ) { + kdDebug() << "(K3bLibDvdCss) unable to seek to " << file->startSector() << endl; + return false; + } + } + + if( title > 0 ) { + QPair p; + int vob = 1; + for( ; vob < 100; ++vob ) { + filename.sprintf( "VIDEO_TS/VTS_%02d_%d.VOB", title, vob ); + file = dynamic_cast( dir->entry( filename ) ); + if( file ) { + if( file->size() % 2048 ) + kdError() << "(K3bLibDvdCss) FILESIZE % 2048 != 0!!!" << endl; + if( vob == 1 ) { + p.first = file->startSector(); + p.second = file->size() / 2048; + kdDebug() << "(K3bLibDvdCss) Get key for /" << filename << " at " << file->startSector() << endl; + if( seek( (int)file->startSector(), DVDCSS_SEEK_KEY ) < 0 ) { + kdDebug() << "(K3bLibDvdCss) unable to seek to " << file->startSector() << endl; + return false; + } + } + else { + p.second += file->size() / 2048; + } + } + else { + // last vob + break; + } + } + --vob; + + // last title + if( vob == 0 ) + break; + + kdDebug() << "(K3bLibDvdCss) Title " << title << " " << vob << " vobs with length " << p.second << endl; + d->titleOffsets.append( p ); + } + } + + --title; + + kdDebug() << "(K3bLibDvdCss) found " << title << " titles." << endl; + + return (title > 0); +} + + +K3bLibDvdCss* K3bLibDvdCss::create() +{ + if( s_libDvdCss == 0 ) { + s_libDvdCss = dlopen( "libdvdcss.so.2", RTLD_LAZY|RTLD_GLOBAL ); + if( s_libDvdCss ) { + k3b_dvdcss_open = (dvdcss_t (*)(char*))dlsym( s_libDvdCss, "dvdcss_open" ); + k3b_dvdcss_close = (int (*)( dvdcss_t ))dlsym( s_libDvdCss, "dvdcss_close" ); + k3b_dvdcss_seek = (int (*)( dvdcss_t, int, int ))dlsym( s_libDvdCss, "dvdcss_seek" ); + k3b_dvdcss_read = (int (*)( dvdcss_t, void*, int, int ))dlsym( s_libDvdCss, "dvdcss_read" ); + + if( !k3b_dvdcss_open || !k3b_dvdcss_close || !k3b_dvdcss_seek || !k3b_dvdcss_read ) { + kdDebug() << "(K3bLibDvdCss) unable to resolve libdvdcss." << endl; + dlclose( s_libDvdCss ); + s_libDvdCss = 0; + } + } + else + kdDebug() << "(K3bLibDvdCss) unable to load libdvdcss." << endl; + } + + if( s_libDvdCss ) + return new K3bLibDvdCss(); + else + return 0; +} diff --git a/libk3b/tools/k3blibdvdcss.h b/libk3b/tools/k3blibdvdcss.h new file mode 100644 index 0000000..308296f --- /dev/null +++ b/libk3b/tools/k3blibdvdcss.h @@ -0,0 +1,84 @@ +/* + * + * $Id: k3blibdvdcss.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_LIBDVDCSS_H_ +#define _K3B_LIBDVDCSS_H_ + +#include "k3b_export.h" + +namespace K3bDevice { + class Device; +} + + +/** + * Wrapper class for libdvdcss. dynamically openes the library if it + * is available on the system. + */ +class LIBK3B_EXPORT K3bLibDvdCss +{ + public: + ~K3bLibDvdCss(); + + static const int DVDCSS_BLOCK_SIZE = 2048; + static const int DVDCSS_NOFLAGS = 0; + static const int DVDCSS_READ_DECRYPT = (1 << 0); + static const int DVDCSS_SEEK_MPEG = (1 << 0); + static const int DVDCSS_SEEK_KEY = (1 << 1); + + /** + * Try to open a Video DVD and authenticate it. + * @return true if the Video DVD could be authenticated successfully, false otherwise. + */ + bool open( K3bDevice::Device* dev ); + void close(); + + int seek( int sector, int flags ); + int read( void* buffer, int sectors, int flags ); + + /** + * This method optimized the seek calls to maximize reading performance. + * It also makes sure we never read unscrambled and scrambled data at the same time. + * + * You have to call crackAllKeys() before using this. Do never call this in combination + * with seek or read! + */ + int readWrapped( void* buffer, int firstSector, int sectors ); + + /** + * Cache all CSS keys to guarantee smooth reading further on. + * This method also creates a title offset list which is needed by readWrapped. + */ + bool crackAllKeys(); + + /** + * returns 0 if the libdvdcss could not + * be found on the system. + * Otherwise you have to take care of + * deleting. + */ + static K3bLibDvdCss* create(); + + private: + class Private; + Private* d; + + K3bLibDvdCss(); + + static void* s_libDvdCss; + static int s_counter; +}; + +#endif diff --git a/libk3b/tools/k3blistview.cpp b/libk3b/tools/k3blistview.cpp new file mode 100644 index 0000000..34a3aa0 --- /dev/null +++ b/libk3b/tools/k3blistview.cpp @@ -0,0 +1,1290 @@ +/* + * + * $Id: k3blistview.cpp 768493 2008-01-30 08:44:05Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#include "k3blistview.h" + +#include "k3bmsfedit.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + + + +// /////////////////////////////////////////////// +// +// K3BLISTVIEWITEM +// +// /////////////////////////////////////////////// + + +class K3bListViewItem::ColumnInfo +{ +public: + ColumnInfo() + : showProgress(false), + progressValue(0), + totalProgressSteps(100), + margin(0), + validator(0) { + editorType = NONE; + button = false; + comboEditable = false; + next = 0; + fontSet = false; + backgroundColorSet = false; + foregroundColorSet = false; + } + + ~ColumnInfo() { + if( next ) + delete next; + } + + bool button; + int editorType; + QStringList comboItems; + bool comboEditable; + bool fontSet; + bool backgroundColorSet; + bool foregroundColorSet; + QFont font; + QColor backgroundColor; + QColor foregroundColor; + ColumnInfo* next; + + bool showProgress; + int progressValue; + int totalProgressSteps; + int margin; + + QValidator* validator; +}; + + + +K3bListViewItem::K3bListViewItem(QListView *parent) + : KListViewItem( parent ) +{ + init(); +} + +K3bListViewItem::K3bListViewItem(QListViewItem *parent) + : KListViewItem( parent ) +{ + init(); +} + +K3bListViewItem::K3bListViewItem(QListView *parent, QListViewItem *after) + : KListViewItem( parent, after ) +{ + init(); +} + +K3bListViewItem::K3bListViewItem(QListViewItem *parent, QListViewItem *after) + : KListViewItem( parent, after ) +{ + init(); +} + + +K3bListViewItem::K3bListViewItem(QListView *parent, + const QString& s1, const QString& s2, + const QString& s3, const QString& s4, + const QString& s5, const QString& s6, + const QString& s7, const QString& s8) + : KListViewItem( parent, s1, s2, s3, s4, s5, s6, s7, s8 ) +{ + init(); +} + + +K3bListViewItem::K3bListViewItem(QListViewItem *parent, + const QString& s1, const QString& s2, + const QString& s3, const QString& s4, + const QString& s5, const QString& s6, + const QString& s7, const QString& s8) + : KListViewItem( parent, s1, s2, s3, s4, s5, s6, s7, s8 ) +{ + init(); +} + + +K3bListViewItem::K3bListViewItem(QListView *parent, QListViewItem *after, + const QString& s1, const QString& s2, + const QString& s3, const QString& s4, + const QString& s5, const QString& s6, + const QString& s7, const QString& s8) + : KListViewItem( parent, after, s1, s2, s3, s4, s5, s6, s7, s8 ) +{ + init(); +} + + +K3bListViewItem::K3bListViewItem(QListViewItem *parent, QListViewItem *after, + const QString& s1, const QString& s2, + const QString& s3, const QString& s4, + const QString& s5, const QString& s6, + const QString& s7, const QString& s8) + : KListViewItem( parent, after, s1, s2, s3, s4, s5, s6, s7, s8 ) +{ + init(); +} + + +K3bListViewItem::~K3bListViewItem() +{ + if( K3bListView* lv = dynamic_cast(listView()) ) + if( lv->currentlyEditedItem() == this ) + lv->hideEditor(); + + if( m_columns ) + delete m_columns; +} + + +void K3bListViewItem::init() +{ + m_columns = 0; + m_vMargin = 0; +} + + +int K3bListViewItem::width( const QFontMetrics& fm, const QListView* lv, int c ) const +{ + return KListViewItem::width( fm, lv, c ) + getColumnInfo(c)->margin*2; +} + + +void K3bListViewItem::setEditor( int column, int editor, const QStringList& cs ) +{ + ColumnInfo* colInfo = getColumnInfo(column); + + colInfo->editorType = editor; + if( !cs.isEmpty() ) + colInfo->comboItems = cs; +} + + +void K3bListViewItem::setValidator( int column, QValidator* v ) +{ + getColumnInfo(column)->validator = v; +} + + +QValidator* K3bListViewItem::validator( int col ) const +{ + return getColumnInfo(col)->validator; +} + + +void K3bListViewItem::setButton( int column, bool on ) +{ + ColumnInfo* colInfo = getColumnInfo(column); + + colInfo->button = on; +} + + +K3bListViewItem::ColumnInfo* K3bListViewItem::getColumnInfo( int col ) const +{ + if( !m_columns ) + m_columns = new ColumnInfo(); + + ColumnInfo* info = m_columns; + int i = 0; + while( i < col ) { + if( !info->next ) + info->next = new ColumnInfo(); + info = info->next; + ++i; + } + + return info; +} + + +int K3bListViewItem::editorType( int col ) const +{ + ColumnInfo* info = getColumnInfo( col ); + return info->editorType; +} + + +bool K3bListViewItem::needButton( int col ) const +{ + ColumnInfo* info = getColumnInfo( col ); + return info->button; +} + + +const QStringList& K3bListViewItem::comboStrings( int col ) const +{ + ColumnInfo* info = getColumnInfo( col ); + return info->comboItems; +} + + +void K3bListViewItem::setFont( int col, const QFont& f ) +{ + ColumnInfo* info = getColumnInfo( col ); + info->fontSet = true; + info->font = f; +} + + +void K3bListViewItem::setBackgroundColor( int col, const QColor& c ) +{ + ColumnInfo* info = getColumnInfo( col ); + info->backgroundColorSet = true; + info->backgroundColor = c; + repaint(); +} + + +void K3bListViewItem::setForegroundColor( int col, const QColor& c ) +{ + ColumnInfo* info = getColumnInfo( col ); + info->foregroundColorSet = true; + info->foregroundColor = c; + repaint(); +} + + +void K3bListViewItem::setDisplayProgressBar( int col, bool displ ) +{ + ColumnInfo* info = getColumnInfo( col ); + info->showProgress = displ; +} + + +void K3bListViewItem::setProgress( int col, int p ) +{ + ColumnInfo* info = getColumnInfo( col ); + if( !info->showProgress ) + setDisplayProgressBar( col, true ); + if( info->progressValue != p ) { + info->progressValue = p; + repaint(); + } +} + + +void K3bListViewItem::setTotalSteps( int col, int steps ) +{ + ColumnInfo* info = getColumnInfo( col ); + info->totalProgressSteps = steps; + + repaint(); +} + + +void K3bListViewItem::setMarginHorizontal( int col, int margin ) +{ + ColumnInfo* info = getColumnInfo( col ); + info->margin = margin; + + repaint(); +} + + +void K3bListViewItem::setMarginVertical( int margin ) +{ + m_vMargin = margin; + repaint(); +} + + +int K3bListViewItem::marginHorizontal( int col ) const +{ + return getColumnInfo( col )->margin; +} + + +int K3bListViewItem::marginVertical() const +{ + return m_vMargin; +} + + +void K3bListViewItem::setup() +{ + KListViewItem::setup(); + + setHeight( height() + 2*m_vMargin ); +} + + +void K3bListViewItem::paintCell( QPainter* p, const QColorGroup& cg, int col, int width, int align ) +{ + ColumnInfo* info = getColumnInfo( col ); + + p->save(); + + QFont oldFont( p->font() ); + QFont newFont = info->fontSet ? info->font : oldFont; + p->setFont( newFont ); + QColorGroup cgh(cg); + if( info->foregroundColorSet ) + cgh.setColor( QColorGroup::Text, info->foregroundColor ); + if( info->backgroundColorSet ) + cgh.setColor( QColorGroup::Base, info->backgroundColor ); + + // in case this is the selected row has a margin we need to repaint the selection bar + if( isSelected() && + (col == 0 || listView()->allColumnsShowFocus()) && + info->margin > 0 ) { + + p->fillRect( 0, 0, info->margin, height(), + cgh.brush( QColorGroup::Highlight ) ); + p->fillRect( width-info->margin, 0, info->margin, height(), + cgh.brush( QColorGroup::Highlight ) ); + } + else { // in case we use the KListView alternate color stuff + p->fillRect( 0, 0, info->margin, height(), + cgh.brush( QColorGroup::Base ) ); + p->fillRect( width-info->margin, 0, info->margin, height(), + cgh.brush( QColorGroup::Base ) ); + } + + // FIXME: the margin (we can only translate horizontally since height() is used for painting) + p->translate( info->margin, 0 ); + + if( info->showProgress ) { + paintProgressBar( p, cgh, col, width-2*info->margin ); + } + else { + paintK3bCell( p, cgh, col, width-2*info->margin, align ); + } + + p->restore(); +} + + +void K3bListViewItem::paintK3bCell( QPainter* p, const QColorGroup& cg, int col, int width, int align ) +{ + QListViewItem::paintCell( p, cg, col, width, align ); +} + + +void K3bListViewItem::paintProgressBar( QPainter* p, const QColorGroup& cgh, int col, int width ) +{ + ColumnInfo* info = getColumnInfo( col ); + + QStyle::SFlags flags = QStyle::Style_Default; + if( listView()->isEnabled() ) + flags |= QStyle::Style_Enabled; + if( listView()->hasFocus() ) + flags |= QStyle::Style_HasFocus; + + // FIXME: the QPainter is translated so 0, m_vMargin is the upper left of our paint rect + QRect r( 0, m_vMargin, width, height()-2*m_vMargin ); + + // create the double buffer pixmap + static QPixmap *doubleBuffer = 0; + if( !doubleBuffer ) + doubleBuffer = new QPixmap; + doubleBuffer->resize( width, height() ); + + QPainter dbPainter( doubleBuffer ); + + // clear the background (we cannot use paintEmptyArea since it's protected in QListView) + if( K3bListView* lv = dynamic_cast(listView()) ) + lv->paintEmptyArea( &dbPainter, r ); + else + dbPainter.fillRect( 0, 0, width, height(), + cgh.brush( QPalette::backgroundRoleFromMode(listView()->viewport()->backgroundMode()) ) ); + + // we want a little additional margin + r.setLeft( r.left()+1 ); + r.setWidth( r.width()-2 ); + r.setTop( r.top()+1 ); + r.setHeight( r.height()-2 ); + + // this might be a stupid hack but most styles do not reimplement drawPrimitive PE_ProgressBarChunk + // so this way the user is happy.... + static QProgressBar* s_dummyProgressBar = 0; + if( !s_dummyProgressBar ) { + s_dummyProgressBar = new QProgressBar(); + } + + s_dummyProgressBar->setTotalSteps( info->totalProgressSteps ); + s_dummyProgressBar->setProgress( info->progressValue ); + + // some styles use the widget's geometry + s_dummyProgressBar->setGeometry( r ); + + listView()->style().drawControl(QStyle::CE_ProgressBarContents, &dbPainter, s_dummyProgressBar, r, cgh, flags ); + listView()->style().drawControl(QStyle::CE_ProgressBarLabel, &dbPainter, s_dummyProgressBar, r, cgh, flags ); + + // now we really paint the progress in the listview + p->drawPixmap( 0, 0, *doubleBuffer ); +} + + + + + + + +K3bCheckListViewItem::K3bCheckListViewItem(QListView *parent) + : K3bListViewItem( parent ), + m_checked(false) +{ +} + + +K3bCheckListViewItem::K3bCheckListViewItem(QListViewItem *parent) + : K3bListViewItem( parent ), + m_checked(false) +{ +} + + +K3bCheckListViewItem::K3bCheckListViewItem(QListView *parent, QListViewItem *after) + : K3bListViewItem( parent, after ), + m_checked(false) +{ +} + + +K3bCheckListViewItem::K3bCheckListViewItem(QListViewItem *parent, QListViewItem *after) + : K3bListViewItem( parent, after ), + m_checked(false) +{ +} + + +bool K3bCheckListViewItem::isChecked() const +{ + return m_checked; +} + + +void K3bCheckListViewItem::setChecked( bool checked ) +{ + m_checked = checked; + repaint(); +} + + +void K3bCheckListViewItem::paintK3bCell( QPainter* p, const QColorGroup& cg, int col, int width, int align ) +{ + K3bListViewItem::paintK3bCell( p, cg, col, width, align ); + + if( col == 0 ) { + if( m_checked ) { + QRect r( 0, marginVertical(), width, /*listView()->style().pixelMetric( QStyle::PM_CheckListButtonSize )*/height()-2*marginVertical() ); + + QStyle::SFlags flags = QStyle::Style_Default; + if( listView()->isEnabled() ) + flags |= QStyle::Style_Enabled; + if( listView()->hasFocus() ) + flags |= QStyle::Style_HasFocus; + if( isChecked() ) + flags |= QStyle::Style_On; + else + flags |= QStyle::Style_Off; + + listView()->style().drawPrimitive( QStyle::PE_CheckMark, p, r, cg, flags ); + } + } +} + + + + + + +// /////////////////////////////////////////////// +// +// K3BLISTVIEW +// +// /////////////////////////////////////////////// + + +class K3bListView::Private +{ +public: + QLineEdit* spinBoxLineEdit; + QLineEdit* msfEditLineEdit; +}; + + +K3bListView::K3bListView( QWidget* parent, const char* name ) + : KListView( parent, name ), + m_noItemVMargin( 20 ), + m_noItemHMargin( 20 ) +{ + d = new Private; + + connect( header(), SIGNAL( sizeChange( int, int, int ) ), + this, SLOT( updateEditorSize() ) ); + + m_editorButton = 0; + m_editorComboBox = 0; + m_editorSpinBox = 0; + m_editorLineEdit = 0; + m_editorMsfEdit = 0; + m_currentEditItem = 0; + m_currentEditColumn = 0; + m_doubleClickForEdit = true; + m_lastClickedItem = 0; +} + +K3bListView::~K3bListView() +{ + delete d; +} + + +QWidget* K3bListView::editor( K3bListViewItem::EditorType t ) const +{ + switch( t ) { + case K3bListViewItem::COMBO: + return m_editorComboBox; + case K3bListViewItem::LINE: + return m_editorLineEdit; + case K3bListViewItem::SPIN: + return m_editorSpinBox; + case K3bListViewItem::MSF: + return m_editorMsfEdit; + default: + return 0; + } +} + + +void K3bListView::clear() +{ + hideEditor(); + KListView::clear(); +} + + +void K3bListView::editItem( K3bListViewItem* item, int col ) +{ + if( item == 0 ) + hideEditor(); + else if( item->isEnabled() ) { + showEditor( item, col ); + } +} + + +void K3bListView::hideEditor() +{ + m_lastClickedItem = 0; + m_currentEditItem = 0; + m_currentEditColumn = 0; + + if( m_editorSpinBox ) + m_editorSpinBox->hide(); + if( m_editorLineEdit ) + m_editorLineEdit->hide(); + if( m_editorComboBox ) + m_editorComboBox->hide(); + if( m_editorButton ) + m_editorButton->hide(); + if( m_editorMsfEdit ) + m_editorMsfEdit->hide(); +} + +void K3bListView::showEditor( K3bListViewItem* item, int col ) +{ + if( !item ) + return; + + if( item->needButton( col ) || item->editorType(col) != K3bListViewItem::NONE ) { + m_currentEditColumn = col; + m_currentEditItem = item; + } + + placeEditor( item, col ); + if( item->needButton( col ) ) { + m_editorButton->show(); + } + switch( item->editorType(col) ) { + case K3bListViewItem::COMBO: + m_editorComboBox->show(); + m_editorComboBox->setFocus(); + m_editorComboBox->setValidator( item->validator(col) ); + break; + case K3bListViewItem::LINE: + m_editorLineEdit->show(); + m_editorLineEdit->setFocus(); + m_editorLineEdit->setValidator( item->validator(col) ); + break; + case K3bListViewItem::SPIN: + m_editorSpinBox->show(); + m_editorSpinBox->setFocus(); + break; + case K3bListViewItem::MSF: + m_editorMsfEdit->show(); + m_editorMsfEdit->setFocus(); + break; + default: + break; + } +} + + +void K3bListView::placeEditor( K3bListViewItem* item, int col ) +{ + ensureItemVisible( item ); + QRect r = itemRect( item ); + + r.setX( contentsToViewport( QPoint(header()->sectionPos( col ), 0) ).x() ); + r.setWidth( header()->sectionSize( col ) - 1 ); + + // check if the column is fully visible + if( visibleWidth() < r.right() ) + r.setRight(visibleWidth()); + + r = QRect( viewportToContents( r.topLeft() ), r.size() ); + + if( item->pixmap( col ) ) { + r.setX( r.x() + item->pixmap(col)->width() ); + } + + // the tree-stuff is painted in the first column + if( col == 0 ) { + r.setX( r.x() + item->depth() * treeStepSize() ); + if( rootIsDecorated() ) + r.setX( r.x() + treeStepSize() ); + } + + if( item->needButton(col) ) { + prepareButton( item, col ); + m_editorButton->setFixedHeight( r.height() ); + // for now we make a square button + m_editorButton->setFixedWidth( m_editorButton->height() ); + r.setWidth( r.width() - m_editorButton->width() ); + moveChild( m_editorButton, r.right(), r.y() ); + } + + if( QWidget* editor = prepareEditor( item, col ) ) { + editor->resize( r.size() ); + // editor->resize( QSize( r.width(), editor->minimumSizeHint().height() ) ); + moveChild( editor, r.x(), r.y() ); + } +} + + +void K3bListView::prepareButton( K3bListViewItem*, int ) +{ + if( !m_editorButton ) { + m_editorButton = new QPushButton( viewport() ); + connect( m_editorButton, SIGNAL(clicked()), + this, SLOT(slotEditorButtonClicked()) ); + } + + // TODO: do some useful things + m_editorButton->setText( "..." ); +} + + +QWidget* K3bListView::prepareEditor( K3bListViewItem* item, int col ) +{ + switch( item->editorType(col) ) { + case K3bListViewItem::COMBO: + if( !m_editorComboBox ) { + m_editorComboBox = new QComboBox( viewport() ); + connect( m_editorComboBox, SIGNAL(activated(const QString&)), + this, SLOT(slotEditorComboBoxActivated(const QString&)) ); + m_editorComboBox->installEventFilter( this ); + } + m_editorComboBox->clear(); + if( item->comboStrings( col ).isEmpty() ) { + m_editorComboBox->insertItem( item->text( col ) ); + } + else { + m_editorComboBox->insertStringList( item->comboStrings(col) ); + int current = item->comboStrings(col).findIndex( item->text(col) ); + if( current != -1 ) + m_editorComboBox->setCurrentItem( current ); + } + return m_editorComboBox; + + case K3bListViewItem::LINE: { + if( !m_editorLineEdit ) { + m_editorLineEdit = new QLineEdit( viewport() ); + m_editorLineEdit->setFrameStyle( QFrame::Box | QFrame::Plain ); + m_editorLineEdit->setLineWidth(1); + m_editorLineEdit->installEventFilter( this ); + } + + QString txt = item->text( col ); + m_editorLineEdit->setText( txt ); + + // select the edit text (handle extensions while doing so) + int pos = txt.findRev( '.' ); + if( pos > 0 ) + m_editorLineEdit->setSelection( 0, pos ); + else + m_editorLineEdit->setSelection( 0, txt.length() ); + + return m_editorLineEdit; + } + + // + // A QSpinBox (and thus also a K3bMsfEdit) uses a QLineEdit), thus + // we have to use this QLineEdit as the actual object to dead with + // + + case K3bListViewItem::SPIN: + if( !m_editorSpinBox ) { + m_editorSpinBox = new QSpinBox( viewport() ); + d->spinBoxLineEdit = static_cast( m_editorSpinBox->child( 0, "QLineEdit" ) ); + connect( m_editorSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotEditorSpinBoxValueChanged(int)) ); + // m_editorSpinBox->installEventFilter( this ); + d->spinBoxLineEdit->installEventFilter( this ); + } + // set the range + m_editorSpinBox->setValue( item->text(col).toInt() ); + return m_editorSpinBox; + + case K3bListViewItem::MSF: + if( !m_editorMsfEdit ) { + m_editorMsfEdit = new K3bMsfEdit( viewport() ); + d->msfEditLineEdit = static_cast( m_editorMsfEdit->child( 0, "QLineEdit" ) ); + connect( m_editorMsfEdit, SIGNAL(valueChanged(int)), + this, SLOT(slotEditorMsfEditValueChanged(int)) ); + // m_editorMsfEdit->installEventFilter( this ); + d->msfEditLineEdit->installEventFilter( this ); + } + m_editorMsfEdit->setText( item->text(col) ); + return m_editorMsfEdit; + + default: + return 0; + } +} + +void K3bListView::setCurrentItem( QListViewItem* i ) +{ + if( !i || i == currentItem() ) + return; + + // I cannot remember why I did this here exactly. However, it resets the + // m_lastClickedItem and thus invalidates the editing. +// doRename(); +// hideEditor(); +// m_currentEditItem = 0; + KListView::setCurrentItem( i ); +} + + +void K3bListView::setNoItemText( const QString& text ) +{ + m_noItemText = text; + triggerUpdate(); +} + + +void K3bListView::viewportPaintEvent( QPaintEvent* e ) +{ + KListView::viewportPaintEvent( e ); +} + + +// FIXME: move this to viewportPaintEvent +void K3bListView::drawContentsOffset( QPainter * p, int ox, int oy, int cx, int cy, int cw, int ch ) +{ + KListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch ); + + if( childCount() == 0 && !m_noItemText.isEmpty()) { + + p->setPen( Qt::darkGray ); + + QStringList lines = QStringList::split( "\n", m_noItemText ); + int xpos = m_noItemHMargin; + int ypos = m_noItemVMargin + p->fontMetrics().height(); + + QStringList::Iterator end ( lines.end() ); + for( QStringList::Iterator str = lines.begin(); str != end; ++str ) { + p->drawText( xpos, ypos, *str ); + ypos += p->fontMetrics().lineSpacing(); + } + } +} + +void K3bListView::paintEmptyArea( QPainter* p, const QRect& rect ) +{ + KListView::paintEmptyArea( p, rect ); + +// if( childCount() == 0 && !m_noItemText.isEmpty()) { + +// QPainter pp( viewport() ); +// pp.fillRect( viewport()->rect(), viewport()->paletteBackgroundColor() ); +// pp.end(); + +// p->setPen( Qt::darkGray ); + +// QStringList lines = QStringList::split( "\n", m_noItemText ); +// int xpos = m_noItemHMargin; +// int ypos = m_noItemVMargin + p->fontMetrics().height(); + +// for( QStringList::Iterator str = lines.begin(); str != lines.end(); str++ ) { +// p->drawText( xpos, ypos, *str ); +// ypos += p->fontMetrics().lineSpacing(); +// } +// } +} + +void K3bListView::resizeEvent( QResizeEvent* e ) +{ + KListView::resizeEvent( e ); + updateEditorSize(); +} + + +void K3bListView::updateEditorSize() +{ + if( m_currentEditItem ) + placeEditor( m_currentEditItem, m_currentEditColumn ); +} + + +void K3bListView::slotEditorLineEditReturnPressed() +{ + if( doRename() ) { + // edit the next line + // TODO: add config for this + if( K3bListViewItem* nextItem = dynamic_cast( m_currentEditItem->nextSibling() ) ) + editItem( nextItem, currentEditColumn() ); + else { + hideEditor(); + + // keep the focus here + viewport()->setFocus(); + } + } +} + + +void K3bListView::slotEditorComboBoxActivated( const QString& ) +{ + doRename(); +// if( renameItem( m_currentEditItem, m_currentEditColumn, str ) ) { +// m_currentEditItem->setText( m_currentEditColumn, str ); +// emit itemRenamed( m_currentEditItem, str, m_currentEditColumn ); +// } +// else { +// for( int i = 0; i < m_editorComboBox->count(); ++i ) { +// if( m_editorComboBox->text(i) == m_currentEditItem->text(m_currentEditColumn) ) { +// m_editorComboBox->setCurrentItem( i ); +// break; +// } +// } +// } +} + + +void K3bListView::slotEditorSpinBoxValueChanged( int ) +{ +// if( renameItem( m_currentEditItem, m_currentEditColumn, QString::number(value) ) ) { +// m_currentEditItem->setText( m_currentEditColumn, QString::number(value) ); +// emit itemRenamed( m_currentEditItem, QString::number(value), m_currentEditColumn ); +// } +// else +// m_editorSpinBox->setValue( m_currentEditItem->text( m_currentEditColumn ).toInt() ); +} + + +void K3bListView::slotEditorMsfEditValueChanged( int ) +{ + // FIXME: do we always need to update the value. Isn't it enough to do it at the end? +// if( renameItem( m_currentEditItem, m_currentEditColumn, QString::number(value) ) ) { +// m_currentEditItem->setText( m_currentEditColumn, QString::number(value) ); +// emit itemRenamed( m_currentEditItem, QString::number(value), m_currentEditColumn ); +// } +// else +// m_editorMsfEdit->setText( m_currentEditItem->text( m_currentEditColumn ) ); +} + + +bool K3bListView::doRename() +{ + if( m_currentEditItem ) { + QString newValue; + switch( m_currentEditItem->editorType( m_currentEditColumn ) ) { + case K3bListViewItem::COMBO: + newValue = m_editorComboBox->currentText(); + break; + case K3bListViewItem::LINE: + newValue = m_editorLineEdit->text(); + break; + case K3bListViewItem::SPIN: + newValue = QString::number(m_editorSpinBox->value()); + break; + case K3bListViewItem::MSF: + newValue = QString::number(m_editorMsfEdit->value()); + break; + } + + if( renameItem( m_currentEditItem, m_currentEditColumn, newValue ) ) { + m_currentEditItem->setText( m_currentEditColumn, newValue ); + emit itemRenamed( m_currentEditItem, newValue, m_currentEditColumn ); + return true; + } + else { + switch( m_currentEditItem->editorType( m_currentEditColumn ) ) { + case K3bListViewItem::COMBO: + for( int i = 0; i < m_editorComboBox->count(); ++i ) { + if( m_editorComboBox->text(i) == m_currentEditItem->text(m_currentEditColumn) ) { + m_editorComboBox->setCurrentItem( i ); + break; + } + } + break; + case K3bListViewItem::LINE: + m_editorLineEdit->setText( m_currentEditItem->text( m_currentEditColumn ) ); + break; + case K3bListViewItem::SPIN: + m_editorSpinBox->setValue( m_currentEditItem->text( m_currentEditColumn ).toInt() ); + break; + case K3bListViewItem::MSF: + m_editorMsfEdit->setText( m_currentEditItem->text( m_currentEditColumn ) ); + break; + } + } + } + + + return false; +} + + +void K3bListView::slotEditorButtonClicked() +{ + slotEditorButtonClicked( m_currentEditItem, m_currentEditColumn ); +} + + +bool K3bListView::renameItem( K3bListViewItem* item, int col, const QString& text ) +{ + Q_UNUSED(item); + Q_UNUSED(col); + Q_UNUSED(text); + return true; +} + + +void K3bListView::slotEditorButtonClicked( K3bListViewItem* item, int col ) +{ + emit editorButtonClicked( item, col ); +} + + +bool K3bListView::eventFilter( QObject* o, QEvent* e ) +{ + if( e->type() == QEvent::KeyPress ) { + QKeyEvent* ke = static_cast(e); + if( ke->key() == Key_Tab ) { + if( o == m_editorLineEdit || + o == d->msfEditLineEdit || + o == d->spinBoxLineEdit ) { + K3bListViewItem* lastEditItem = m_currentEditItem; + + doRename(); + + if( lastEditItem ) { + // can we rename one of the other columns? + int col = currentEditColumn()+1; + while( col < columns() && lastEditItem->editorType( col ) == K3bListViewItem::NONE ) + ++col; + if( col < columns() ) + editItem( lastEditItem, col ); + else { + hideEditor(); + + // keep the focus here + viewport()->setFocus(); + + // search for the next editable item + while( K3bListViewItem* nextItem = + dynamic_cast( lastEditItem->nextSibling() ) ) { + // edit first column + col = 0; + while( col < columns() && nextItem->editorType( col ) == K3bListViewItem::NONE ) + ++col; + if( col < columns() ) { + editItem( nextItem, col ); + break; + } + + lastEditItem = nextItem; + } + } + } + + return true; + } + } + if( ke->key() == Key_Return || + ke->key() == Key_Enter ) { + if( o == m_editorLineEdit || + o == d->msfEditLineEdit || + o == d->spinBoxLineEdit ) { + K3bListViewItem* lastEditItem = m_currentEditItem; + doRename(); + + if( K3bListViewItem* nextItem = + dynamic_cast( lastEditItem->nextSibling() ) ) + editItem( nextItem, currentEditColumn() ); + else { + hideEditor(); + + // keep the focus here + viewport()->setFocus(); + } + + return true; + } + } + else if( ke->key() == Key_Escape ) { + if( o == m_editorLineEdit || + o == d->msfEditLineEdit || + o == d->spinBoxLineEdit ) { + hideEditor(); + + // keep the focus here + viewport()->setFocus(); + + return true; + } + } + } + + else if( e->type() == QEvent::MouseButtonPress && o == viewport() ) { + + // first let's grab the focus + viewport()->setFocus(); + + QMouseEvent* me = static_cast( e ); + QListViewItem* item = itemAt( me->pos() ); + int col = header()->sectionAt( me->pos().x() ); + if( K3bCheckListViewItem* ci = dynamic_cast( item ) ) { + if( col == 0 ) { + // FIXME: improve this click area! + ci->setChecked( !ci->isChecked() ); + return true; + } + } + + if( me->button() == QMouseEvent::LeftButton ) { + if( item != m_currentEditItem || m_currentEditColumn != col ) { + doRename(); + if( K3bListViewItem* k3bItem = dynamic_cast(item) ) { + if( me->pos().x() > item->depth()*treeStepSize() && + item->isEnabled() && + (m_lastClickedItem == item || !m_doubleClickForEdit) ) + showEditor( k3bItem, col ); + else { + hideEditor(); + + // keep the focus here + viewport()->setFocus(); + } + } + else { + hideEditor(); + + // keep the focus here + viewport()->setFocus(); + } + + // do not count clicks in the item tree for editing + if( item && me->pos().x() > item->depth()*treeStepSize() ) + m_lastClickedItem = item; + } + } + } + + else if( e->type() == QEvent::FocusOut ) { + if( o == m_editorLineEdit || + o == d->msfEditLineEdit || + o == d->spinBoxLineEdit || + o == m_editorComboBox ) { + // make sure we did not lose the focus to one of the edit widgets' children + if( !qApp->focusWidget() || qApp->focusWidget()->parentWidget() != o ) { + doRename(); + hideEditor(); + } + } + } + + return KListView::eventFilter( o, e ); +} + + +void K3bListView::setK3bBackgroundPixmap( const QPixmap& pix, int pos ) +{ + m_backgroundPixmap = pix; + m_backgroundPixmapPosition = pos; +} + + +void K3bListView::viewportResizeEvent( QResizeEvent* e ) +{ + if( !m_backgroundPixmap.isNull() ) { + + QSize size = viewport()->size().expandedTo( QSize( contentsWidth(), contentsHeight() ) ); + + QPixmap bgPix( size ); + + // FIXME: let the user specify the color + bgPix.fill( colorGroup().base() ); + + if( bgPix.width() < m_backgroundPixmap.width() || + bgPix.height() < m_backgroundPixmap.height() ) { + QPixmap newBgPix( m_backgroundPixmap.convertToImage().scale( bgPix.size(), QImage::ScaleMin ) ); + if( m_backgroundPixmapPosition == TOP_LEFT ) + bitBlt( &bgPix, 0, 0, + &newBgPix, 0, 0, + newBgPix.width(), newBgPix.height() ); + else { + int dx = bgPix.width() / 2 - m_backgroundPixmap.width() /2; + int dy = bgPix.height() / 2 - m_backgroundPixmap.height() /2; + bitBlt( &bgPix, dx, dy, &newBgPix, 0, 0, + newBgPix.width(), newBgPix.height() ); + } + } + else { + if( m_backgroundPixmapPosition == TOP_LEFT ) + bitBlt( &bgPix, 0, 0, + &m_backgroundPixmap, 0, 0, + m_backgroundPixmap.width(), m_backgroundPixmap.height() ); + else { + int dx = bgPix.width() / 2 - m_backgroundPixmap.width() /2; + int dy = bgPix.height() / 2 - m_backgroundPixmap.height() /2; + bitBlt( &bgPix, dx, dy, &m_backgroundPixmap, 0, 0, + m_backgroundPixmap.width(), m_backgroundPixmap.height() ); + } + } + + viewport()->setPaletteBackgroundPixmap( bgPix ); + } + + KListView::viewportResizeEvent( e ); +} + + +QListViewItem* K3bListView::parentItem( QListViewItem* item ) +{ + if( !item ) + return 0; + if( item->parent() ) + return item->parent(); + else + return K3bListView::parentItem( item->itemAbove() ); +} + + +KPixmap K3bListView::createDragPixmap( const QPtrList& items ) +{ + // + // Create drag pixmap. + // If there are too many items fade the pixmap using the mask + // always fade invisible items + // + int width = header()->width(); + int height = 0; + for( QPtrListIterator it( items ); *it; ++it ) { + QRect r = itemRect( *it ); + + if( r.isValid() ) { + height += ( *it )->height(); + } + } + + // now we should have a range top->bottom which includes all visible items + + // there are two situations in which we fade the pixmap on the top or the bottom: + // 1. there are invisible items above (below) the visible + // 2. the range is way too big + + // FIXME: how do we determine if there are invisible items outside our range? + + KPixmap pix; + pix.resize( width, height ); + pix.fill( Qt::white ); + // QBitmap mask( width, bottom-top ); + + // now paint all the visible items into the pixmap + // FIXME: only paint the visible items + QPainter p( &pix ); + for( QListViewItemIterator it( this ); *it; ++it ) { + QListViewItem* item = *it; + + // FIXME: items on other than the top level have a smaller first column + // the same goes for all items if root is decorated + bool alreadyDrawing = false; + QRect r = itemRect( item ); + if( r.isValid() ) { + if( items.containsRef( item ) ) { + // paint all columns + int x = 0; + for( int i = 0; i < columns(); ++i ) { + item->paintCell( &p, colorGroup(), i, columnWidth( i ), columnAlignment( i ) ); + p.translate( columnWidth( i ), 0 ); + x += columnWidth( i ); + } + + p.translate( -x, item->height() ); + + alreadyDrawing = true; + } + else if( alreadyDrawing ) + p.translate( 0, item->height() ); + + if( p.worldMatrix().dy() >= pix.height() ) + break; + } + } + + // make it a little lighter + KPixmapEffect::fade( pix, 0.3, Qt::white ); + + // FIXME: fade the pixmap at the right side if the items are longer than width + + return pix; +} + +#include "k3blistview.moc" diff --git a/libk3b/tools/k3blistview.h b/libk3b/tools/k3blistview.h new file mode 100644 index 0000000..f8eb2ad --- /dev/null +++ b/libk3b/tools/k3blistview.h @@ -0,0 +1,296 @@ +/* + * + * $Id: k3blistview.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BLISTVIEW_H +#define K3BLISTVIEW_H + + +#include +#include "k3b_export.h" +#include +#include +#include +#include + +class QPainter; +class QPushButton; +class QIconSet; +class QResizeEvent; +class QComboBox; +class QSpinBox; +class QLineEdit; +class QEvent; +class QValidator; +class K3bMsfEdit; + +class K3bListView; + + +class LIBK3B_EXPORT K3bListViewItem : public KListViewItem +{ + public: + K3bListViewItem(QListView *parent); + K3bListViewItem(QListViewItem *parent); + K3bListViewItem(QListView *parent, QListViewItem *after); + K3bListViewItem(QListViewItem *parent, QListViewItem *after); + + K3bListViewItem(QListView *parent, + const QString&, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null); + + K3bListViewItem(QListViewItem *parent, + const QString&, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null); + + K3bListViewItem(QListView *parent, QListViewItem *after, + const QString&, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null); + + K3bListViewItem(QListViewItem *parent, QListViewItem *after, + const QString&, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null, + const QString& = QString::null, const QString& = QString::null); + + virtual ~K3bListViewItem(); + + /** + * reimplemented from KListViewItem + */ + void setup(); + + virtual int width( const QFontMetrics& fm, const QListView* lv, int c ) const; + + void setEditor( int col, int type, const QStringList& = QStringList() ); + void setButton( int col, bool ); + + void setValidator( int col, QValidator* v ); + QValidator* validator( int col ) const; + + int editorType( int col ) const; + bool needButton( int col ) const; + const QStringList& comboStrings( int col ) const; + + enum EditorType { NONE, COMBO, LINE, SPIN, MSF }; + + void setFont( int col, const QFont& f ); + void setBackgroundColor( int col, const QColor& ); + void setForegroundColor( int col, const QColor& ); + + void setDisplayProgressBar( int col, bool ); + void setProgress( int, int ); + void setTotalSteps( int col, int steps ); + + /** + * The margin left and right of the cell + */ + void setMarginHorizontal( int col, int margin ); + + /** + * The top and button margin of the cell + */ + void setMarginVertical( int margin ); + + int marginHorizontal( int col ) const; + int marginVertical() const; + + /** + * Do not reimplement this but paintK3bCell to use the margin and background stuff. + */ + virtual void paintCell( QPainter* p, const QColorGroup& cg, int col, int width, int align ); + + virtual void paintK3bCell( QPainter* p, const QColorGroup& cg, int col, int width, int align ); + + private: + void paintProgressBar( QPainter* p, const QColorGroup& cgh, int col, int width ); + + class ColumnInfo; + mutable ColumnInfo* m_columns; + + ColumnInfo* getColumnInfo( int ) const; + void init(); + + int m_vMargin; +}; + + +class LIBK3B_EXPORT K3bCheckListViewItem : public K3bListViewItem +{ + public: + K3bCheckListViewItem(QListView *parent); + K3bCheckListViewItem(QListViewItem *parent); + K3bCheckListViewItem(QListView *parent, QListViewItem *after); + K3bCheckListViewItem(QListViewItem *parent, QListViewItem *after); + + virtual bool isChecked() const; + virtual void setChecked( bool checked ); + + protected: + virtual void paintK3bCell( QPainter* p, const QColorGroup& cg, int col, int width, int align ); + + private: + bool m_checked; +}; + + + +class LIBK3B_EXPORT K3bListView : public KListView +{ + friend class K3bListViewItem; + + Q_OBJECT + + public: + K3bListView (QWidget *parent = 0, const char *name = 0); + virtual ~K3bListView(); + + virtual void setCurrentItem( QListViewItem* ); + + K3bListViewItem* currentlyEditedItem() const { return m_currentEditItem; } + + QWidget* editor( K3bListViewItem::EditorType ) const; + + enum BgPixPosition { + TOP_LEFT, + CENTER + }; + + /** + * This will set a background pixmap which is not tiled. + * @param pos position on the viewport. + */ + void setK3bBackgroundPixmap( const QPixmap&, int pos = CENTER ); + + /** + * Create a faded pixmap showing the items. + */ + KPixmap createDragPixmap( const QPtrList& items ); + + /** + * Searches for the first item above @p i which is one level higher. + * For 1st level items this will always be the listview's root item. + */ + static QListViewItem* parentItem( QListViewItem* i ); + + signals: + void editorButtonClicked( K3bListViewItem*, int ); + + public slots: + void setNoItemText( const QString& ); + // void setNoItemPixmap( const QPixmap& ); + void setNoItemVerticalMargin( int i ) { m_noItemVMargin = i; } + void setNoItemHorizontalMargin( int i ) { m_noItemHMargin = i; } + void setDoubleClickForEdit( bool b ) { m_doubleClickForEdit = b; } + void hideEditor(); + void editItem( K3bListViewItem*, int ); + + virtual void clear(); + + private slots: + void updateEditorSize(); + virtual void slotEditorLineEditReturnPressed(); + virtual void slotEditorComboBoxActivated( const QString& ); + virtual void slotEditorSpinBoxValueChanged( int ); + virtual void slotEditorMsfEditValueChanged( int ); + virtual void slotEditorButtonClicked(); + + protected slots: + void showEditor( K3bListViewItem*, int col ); + void placeEditor( K3bListViewItem*, int col ); + + /** + * This is called whenever one of the editor's contents changes + * the default implementation just returnes true + * + * FIXME: should be called something like mayRename + */ + virtual bool renameItem( K3bListViewItem*, int, const QString& ); + + /** + * default impl just emits signal + * editorButtonClicked(...) + */ + virtual void slotEditorButtonClicked( K3bListViewItem*, int ); + + protected: + /** + * calls KListView::drawContentsOffset + * and paints a the noItemText if no item is in the list + */ + virtual void drawContentsOffset ( QPainter * p, int ox, int oy, int cx, int cy, int cw, int ch ); + virtual void resizeEvent( QResizeEvent* ); + virtual void paintEmptyArea( QPainter*, const QRect& rect ); + + /** + * Reimplemented for internal reasons. + * + * Further reimplementations should call this function or else some features may not work correctly. + * + * The API is unaffected. + */ + virtual void viewportResizeEvent( QResizeEvent* ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void viewportPaintEvent(QPaintEvent*); + + virtual bool eventFilter( QObject*, QEvent* ); + + K3bListViewItem* currentEditItem() const { return m_currentEditItem; } + int currentEditColumn() const { return m_currentEditColumn; } + + private: + QWidget* prepareEditor( K3bListViewItem* item, int col ); + void prepareButton( K3bListViewItem* item, int col ); + bool doRename(); + + QString m_noItemText; + // QPixmap m_noItemPixmap; + int m_noItemVMargin; + int m_noItemHMargin; + + K3bListViewItem* m_currentEditItem; + int m_currentEditColumn; + + bool m_doubleClickForEdit; + QListViewItem* m_lastClickedItem; + + QPushButton* m_editorButton; + QComboBox* m_editorComboBox; + QSpinBox* m_editorSpinBox; + QLineEdit* m_editorLineEdit; + K3bMsfEdit* m_editorMsfEdit; + + QPixmap m_backgroundPixmap; + int m_backgroundPixmapPosition; + + class Private; + Private* d; +}; + + +#endif diff --git a/libk3b/tools/k3blistviewitemanimator.cpp b/libk3b/tools/k3blistviewitemanimator.cpp new file mode 100644 index 0000000..1c729b6 --- /dev/null +++ b/libk3b/tools/k3blistviewitemanimator.cpp @@ -0,0 +1,137 @@ +/* + * + * $Id: k3blistviewitemanimator.cpp 689561 2007-07-18 15:19:38Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3blistviewitemanimator.h" + +#include +#include + +#include +#include + + +K3bListViewItemAnimator::K3bListViewItemAnimator( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + init(); +} + + +K3bListViewItemAnimator::K3bListViewItemAnimator( QListViewItem* item, int col, QObject* parent, const char* name ) + : QObject( parent, name ) +{ + init(); + setItem( item, col ); +} + + +K3bListViewItemAnimator::~K3bListViewItemAnimator() +{ +} + + +QListViewItem* K3bListViewItemAnimator::item() const +{ + return m_item; +} + + +void K3bListViewItemAnimator::init() +{ + m_item = 0; + m_column = 0; + m_timer = new QTimer( this ); + connect( m_timer, SIGNAL(timeout()), this, SLOT(slotAnimate()) ); +} + + +void K3bListViewItemAnimator::start() +{ + if( m_item && !m_pixmap.isNull() ) { + m_animationStep = 0; + m_animationBack = false; + m_timer->start( 150 ); + } + else + stop(); +} + + +void K3bListViewItemAnimator::stop() +{ + m_timer->stop(); +} + + +void K3bListViewItemAnimator::setItem( QListViewItem* item, int col ) +{ + m_item = item; + m_column = col; + m_pixmap = *item->pixmap(col); + m_fadeColor = item->listView()->colorGroup().base(); + start(); +} + + +void K3bListViewItemAnimator::setPixmap( const QPixmap& p ) +{ + m_pixmap = p; + start(); +} + + +void K3bListViewItemAnimator::setColumn( int col ) +{ + m_column = col; + start(); +} + + +void K3bListViewItemAnimator::setFadeColor( const QColor& c ) +{ + m_fadeColor = c; + start(); +} + + +void K3bListViewItemAnimator::slotAnimate() +{ + if( m_item->isVisible() ) { + double val = (double)m_animationStep; + val /= 10.0; + // we need a temp pixmap since KPixmapEffect changes our pixmap + KPixmap pix( m_pixmap ); + m_item->setPixmap( m_column, KPixmapEffect::fade( pix, val, m_fadeColor ) );; + } + + if( m_animationBack ) { + --m_animationStep; + if( m_animationStep < 0 ) { + // two steps full + m_animationStep = 0; + m_animationBack = false; + } + } + else { + ++m_animationStep; + // do not fade it completely + if( m_animationStep > 9 ) { + m_animationStep = 8; + m_animationBack = true; + } + } +} + +#include "k3blistviewitemanimator.moc" diff --git a/libk3b/tools/k3blistviewitemanimator.h b/libk3b/tools/k3blistviewitemanimator.h new file mode 100644 index 0000000..200079a --- /dev/null +++ b/libk3b/tools/k3blistviewitemanimator.h @@ -0,0 +1,78 @@ +/* + * + * $Id: k3blistviewitemanimator.h 689561 2007-07-18 15:19:38Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_LISTVIEWITEM_ANIMATOR_H_ +#define _K3B_LISTVIEWITEM_ANIMATOR_H_ + +#include +#include +#include "k3b_export.h" + +class QListViewItem; +class QTimer; + + +/** + * Fades an icon on a listview item in and out. + */ +class LIBK3B_EXPORT K3bListViewItemAnimator : public QObject +{ + Q_OBJECT + + public: + K3bListViewItemAnimator( QObject* parent = 0, const char* name = 0 ); + /** + * Will use the items pixmap. + */ + K3bListViewItemAnimator( QListViewItem* item, int col, QObject* parent = 0, const char* name = 0 ); + ~K3bListViewItemAnimator(); + + QListViewItem* item() const; + + public slots: + void start(); + void stop(); + + void setItem( QListViewItem*, int col ); + + /** + * Default is the pixmap from the item. + */ + void setPixmap( const QPixmap& ); + + void setColumn( int col ); + + /** + * Default is the base color of the listview. + */ + void setFadeColor( const QColor& ); + + private slots: + void slotAnimate(); + + private: + void init(); + + int m_animationStep; + bool m_animationBack; + QPixmap m_pixmap; + QColor m_fadeColor; + QListViewItem* m_item; + int m_column; + + QTimer* m_timer; +}; + +#endif diff --git a/libk3b/tools/k3bmd5job.cpp b/libk3b/tools/k3bmd5job.cpp new file mode 100644 index 0000000..2679f33 --- /dev/null +++ b/libk3b/tools/k3bmd5job.cpp @@ -0,0 +1,322 @@ +/* + * + * $Id: k3bmd5job.cpp 633751 2007-02-15 08:22:49Z trueg $ + * Copyright (C) 2003-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bmd5job.h" +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + + +class K3bMd5Job::K3bMd5JobPrivate +{ +public: + K3bMd5JobPrivate() + : fileDes(-1), + fdNotifier(0), + finished(true), + data(0), + isoFile(0), + maxSize(0), + lastProgress(0) { + } + + KMD5 md5; + K3bFileSplitter file; + QTimer timer; + QString filename; + int fileDes; + K3bDevice::Device* device; + QSocketNotifier* fdNotifier; + + bool finished; + char* data; + const K3bIso9660File* isoFile; + + unsigned long long maxSize; + unsigned long long readData; + + int lastProgress; + + KIO::filesize_t imageSize; + + static const int BUFFERSIZE = 2048*10; +}; + + +K3bMd5Job::K3bMd5Job( K3bJobHandler* jh, QObject* parent, const char* name ) + : K3bJob( jh, parent, name ) +{ + d = new K3bMd5JobPrivate; + d->data = new char[K3bMd5JobPrivate::BUFFERSIZE]; + connect( &d->timer, SIGNAL(timeout()), + this, SLOT(slotUpdate()) ); +} + + +K3bMd5Job::~K3bMd5Job() +{ + delete [] d->data; + delete d; +} + + +void K3bMd5Job::start() +{ + cancel(); + + jobStarted(); + d->readData = 0; + + if( d->isoFile ) { + d->imageSize = d->isoFile->size(); + } + else if( !d->filename.isEmpty() ) { + if( !QFile::exists( d->filename ) ) { + emit infoMessage( i18n("Could not find file %1").arg(d->filename), ERROR ); + jobFinished(false); + return; + } + + d->file.setName( d->filename ); + if( !d->file.open( IO_ReadOnly ) ) { + emit infoMessage( i18n("Could not open file %1").arg(d->filename), ERROR ); + jobFinished(false); + return; + } + + d->imageSize = K3b::filesize( KURL::fromPathOrURL(d->filename) ); + } + else + d->imageSize = 0; + + if( d->device ) { + // + // Let the drive determine the optimal reading speed + // + d->device->setSpeed( 0xffff, 0xffff ); + } + + d->md5.reset(); + d->finished = false; + if( d->fileDes != -1 ) + setupFdNotifier(); + else + d->timer.start(0); +} + + +void K3bMd5Job::setupFdNotifier() +{ + // the QSocketNotifier will fire once the fd is closed + delete d->fdNotifier; + d->fdNotifier = new QSocketNotifier( d->fileDes, QSocketNotifier::Read, this ); + connect( d->fdNotifier, SIGNAL(activated(int)), this, SLOT(slotUpdate()) ); + d->fdNotifier->setEnabled( true ); +} + + +void K3bMd5Job::cancel() +{ + if( !d->finished ) { + stopAll(); + + emit canceled(); + jobFinished( false ); + } +} + + +void K3bMd5Job::setFile( const QString& filename ) +{ + d->filename = filename; + d->isoFile = 0; + d->fileDes = -1; + d->device = 0; +} + + +void K3bMd5Job::setFile( const K3bIso9660File* file ) +{ + d->isoFile = file; + d->fileDes = -1; + d->filename.truncate(0); + d->device = 0; +} + + +void K3bMd5Job::setFd( int fd ) +{ + d->fileDes = fd; + d->filename.truncate(0); + d->isoFile = 0; + d->device = 0; +} + + +void K3bMd5Job::setDevice( K3bDevice::Device* dev ) +{ + d->device = dev; + d->fileDes = -1; + d->filename.truncate(0); + d->isoFile = 0; +} + + +void K3bMd5Job::setMaxReadSize( unsigned long long size ) +{ + d->maxSize = size; +} + + +void K3bMd5Job::slotUpdate() +{ + if( !d->finished ) { + + // determine bytes to read + unsigned int readSize = K3bMd5JobPrivate::BUFFERSIZE; + if( d->maxSize > 0 ) + readSize = QMIN( readSize, d->maxSize - d->readData ); + + if( readSize <= 0 ) { + // kdDebug() << "(K3bMd5Job) reached max size of " << d->maxSize << ". Stopping." << endl; + emit debuggingOutput( "K3bMd5Job", QString("Reached max read of %1. Stopping after %2 bytes.").arg(d->maxSize).arg(d->readData) ); + stopAll(); + emit percent( 100 ); + jobFinished(true); + } + else { + int read = 0; + + // + // read from the iso9660 file + // + if( d->isoFile ) { + read = d->isoFile->read( d->readData, d->data, readSize ); + } + + // + // read from the device + // + else if( d->device ) { + // + // when reading from a device we always read multiples of 2048 bytes. + // Only the last sector may not be used completely. + // + unsigned long sector = d->readData/2048; + unsigned int sectorCnt = QMAX( readSize/2048, 1 ); + read = -1; + if( d->device->read10( reinterpret_cast(d->data), + sectorCnt*2048, + sector, + sectorCnt ) ) + read = QMIN( readSize, sectorCnt*2048 ); + } + + // + // read from the file + // + else if( d->fileDes < 0 ) { + read = d->file.readBlock( d->data, readSize ); + } + + // + // reading from the file descriptor + // + else { + read = ::read( d->fileDes, d->data, readSize ); + } + + if( read < 0 ) { + emit infoMessage( i18n("Error while reading from file %1").arg(d->filename), ERROR ); + stopAll(); + jobFinished(false); + } + else if( read == 0 ) { + // kdDebug() << "(K3bMd5Job) read all data. Total size: " << d->readData << ". Stopping." << endl; + emit debuggingOutput( "K3bMd5Job", QString("All data read. Stopping after %1 bytes.").arg(d->readData) ); + stopAll(); + emit percent( 100 ); + jobFinished(true); + } + else { + d->readData += read; + d->md5.update( d->data, read ); + int progress = 0; + if( d->isoFile || !d->filename.isEmpty() ) + progress = (int)((double)d->readData * 100.0 / (double)d->imageSize); + else if( d->maxSize > 0 ) + progress = (int)((double)d->readData * 100.0 / (double)d->maxSize); + + if( progress != d->lastProgress ) { + d->lastProgress = progress; + emit percent( progress ); + } + } + } + } +} + + +QCString K3bMd5Job::hexDigest() +{ + if( d->finished ) + return d->md5.hexDigest(); + else + return ""; +} + + +QCString K3bMd5Job::base64Digest() +{ + if( d->finished ) + return d->md5.base64Digest(); + else + return ""; + +} + + +void K3bMd5Job::stop() +{ + emit debuggingOutput( "K3bMd5Job", QString("Stopped manually after %1 bytes.").arg(d->readData) ); + stopAll(); + jobFinished( true ); +} + + +void K3bMd5Job::stopAll() +{ + if( d->fdNotifier ) + d->fdNotifier->setEnabled( false ); + if( d->file.isOpen() ) + d->file.close(); + d->timer.stop(); + d->finished = true; +} + +#include "k3bmd5job.moc" diff --git a/libk3b/tools/k3bmd5job.h b/libk3b/tools/k3bmd5job.h new file mode 100644 index 0000000..cd64795 --- /dev/null +++ b/libk3b/tools/k3bmd5job.h @@ -0,0 +1,92 @@ +/* + * + * $Id: k3bmd5job.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_MD5_JOB_H_ +#define _K3B_MD5_JOB_H_ + +#include +#include +#include "k3b_export.h" + +namespace K3bDevice { + class Device; +} + +class K3bIso9660File; + + +class LIBK3B_EXPORT K3bMd5Job : public K3bJob +{ + Q_OBJECT + + public: + K3bMd5Job( K3bJobHandler* jh , QObject* parent = 0, const char* name = 0 ); + ~K3bMd5Job(); + + QCString hexDigest(); + QCString base64Digest(); + + public slots: + void start(); + void stop(); + void cancel(); + + // FIXME: read from QIODevice and thus add K3bFileSplitter support + + /** + * read from a file. + * + * Be aware that the K3bMd5Job uses K3bFileSplitter to read splitted + * images. In the future this will be changed with the introduction + * of a setIODevice method. + */ + void setFile( const QString& filename ); + + /** + * read from an iso9660 file + */ + void setFile( const K3bIso9660File* ); + + /** + * read from a device + * This should be used in combination with setMaxReadSize + */ + void setDevice( K3bDevice::Device* dev ); + + /** + * read from the opened file descriptor. + * One needs to set the max read length or call stop() + * to finish calculation. + */ + void setFd( int fd ); + + /** + * Set the maximum bytes to read. + */ + void setMaxReadSize( unsigned long long ); + + private slots: + void slotUpdate(); + + private: + void setupFdNotifier(); + void stopAll(); + + class K3bMd5JobPrivate; + K3bMd5JobPrivate* d; +}; + +#endif diff --git a/libk3b/tools/k3bmsfedit.cpp b/libk3b/tools/k3bmsfedit.cpp new file mode 100644 index 0000000..13ad0a3 --- /dev/null +++ b/libk3b/tools/k3bmsfedit.cpp @@ -0,0 +1,153 @@ +/* + * + * $Id: k3bmsfedit.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + + +#include "k3bmsfedit.h" +#include "k3bglobals.h" + +#include +#include +#include +#include +#include + + + +K3bMsfValidator::K3bMsfValidator( QObject* parent, const char* name ) + : QRegExpValidator( K3b::Msf::regExp(), parent, name ) +{ +} + + + +K3bMsfEdit::K3bMsfEdit( QWidget* parent, const char* name ) + : QSpinBox( parent, name ) +{ + setValidator( new K3bMsfValidator( this ) ); + setMinValue( 0 ); + // some very high value (10000 minutes) + setMaxValue( 10000*60*75 ); + + connect( this, SIGNAL(valueChanged(int)), + this, SLOT(slotValueChanged(int)) ); +} + + +K3bMsfEdit::~K3bMsfEdit() +{} + + +QSize K3bMsfEdit::sizeHint() const +{ + // more or less copied from QSpinBox + constPolish(); + QSize sz = editor()->sizeHint(); + int h = sz.height(); + QFontMetrics fm( font() ); + int w = fm.width( "00:00:00" ); + int wx = fm.width( ' ' )*2; + int frame = style().pixelMetric( QStyle::PM_SpinBoxFrameWidth ); + return style().sizeFromContents(QStyle::CT_SpinBox, this, + QSize( w + wx + downRect().width() + frame*2, + h + frame*2). + expandedTo( QApplication::globalStrut() )); +} + + +QString K3bMsfEdit::mapValueToText( int value ) +{ + return K3b::framesToString( value, true ); +} + + +K3b::Msf K3bMsfEdit::msfValue() const +{ + return K3b::Msf(value()); +} + + +void K3bMsfEdit::setMsfValue( const K3b::Msf& msf ) +{ + setValue( msf.totalFrames() ); +} + + +int K3bMsfEdit::mapTextToValue( bool* ok ) +{ + return K3b::Msf::fromString( text(), ok ).lba(); +} + + +void K3bMsfEdit::setText( const QString& str ) +{ + bool ok; + editor()->setText( str ); + setValue( mapTextToValue( &ok) ); +} + + +void K3bMsfEdit::setFrameStyle( int style ) +{ + editor()->setFrameStyle( style ); +} + +void K3bMsfEdit::setLineWidth( int v ) +{ + editor()->setLineWidth( v ); +} + +void K3bMsfEdit::setValue( int v ) +{ + int i = editor()->cursorPosition(); + QSpinBox::setValue( v ); + editor()->setCursorPosition( i ); +} + +void K3bMsfEdit::stepUp() +{ + setValue( value() + currentStepValue() ); +} + +void K3bMsfEdit::stepDown() +{ + setValue( value() - currentStepValue() ); +} + +int K3bMsfEdit::currentStepValue() const +{ + int val = 1; + + // look if we are currently editing minutes or seconds + QString text = editor()->text(); + if( text.length() == 8 ) { + text = text.mid( editor()->cursorPosition() ); + int num = text.contains( ':' ); + if( num == 1 ) + val = 75; + else if( num == 2 ) + val = 60*75; + } + + return val; +} + + +void K3bMsfEdit::slotValueChanged( int v ) +{ + emit valueChanged( K3b::Msf(v) ); +} + +#include "k3bmsfedit.moc" diff --git a/libk3b/tools/k3bmsfedit.h b/libk3b/tools/k3bmsfedit.h new file mode 100644 index 0000000..c573910 --- /dev/null +++ b/libk3b/tools/k3bmsfedit.h @@ -0,0 +1,70 @@ +/* + * + * $Id: k3bmsfedit.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3B_MSF_EDIT_H +#define K3B_MSF_EDIT_H + + +#include +#include +#include + +#include +#include "k3b_export.h" + +class K3bMsfValidator : public QRegExpValidator +{ + public: + K3bMsfValidator( QObject* parent = 0, const char* name = 0 ); +}; + + +class LIBK3B_EXPORT K3bMsfEdit : public QSpinBox +{ + Q_OBJECT + + public: + K3bMsfEdit( QWidget* parent = 0, const char* name = 0 ); + ~K3bMsfEdit(); + + QSize sizeHint() const; + + void setFrameStyle( int style ); + void setLineWidth(int); + + K3b::Msf msfValue() const; + + signals: + void valueChanged( const K3b::Msf& ); + + public slots: + void setValue( int v ); + void setText( const QString& ); + void setMsfValue( const K3b::Msf& ); + void stepUp(); + void stepDown(); + + protected: + QString mapValueToText( int ); + int mapTextToValue( bool* ok ); + int currentStepValue() const; + + private slots: + void slotValueChanged( int ); +}; + + +#endif diff --git a/libk3b/tools/k3bmultichoicedialog.cpp b/libk3b/tools/k3bmultichoicedialog.cpp new file mode 100644 index 0000000..4c12554 --- /dev/null +++ b/libk3b/tools/k3bmultichoicedialog.cpp @@ -0,0 +1,191 @@ +/* + * + * $Id: k3bmultichoicedialog.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bmultichoicedialog.h" +#include "k3bstdguiitems.h" +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +class K3bMultiChoiceDialog::Private +{ +public: + Private() + : mapper(0), + buttonLayout(0) { + } + + QSignalMapper* mapper; + QPtrList buttons; + QHBoxLayout* buttonLayout; + + bool buttonClicked; +}; + + +// from kmessagebox.cpp +static QPixmap themedMessageBoxIcon(QMessageBox::Icon icon) +{ + QString icon_name; + + switch(icon) { + case QMessageBox::NoIcon: + return QPixmap(); + break; + case QMessageBox::Information: + icon_name = "messagebox_info"; + break; + case QMessageBox::Warning: + icon_name = "messagebox_warning"; + break; + case QMessageBox::Critical: + icon_name = "messagebox_critical"; + break; + default: + break; + } + + QPixmap ret = KApplication::kApplication()->iconLoader()->loadIcon(icon_name, KIcon::NoGroup, KIcon::SizeMedium, KIcon::DefaultState, 0, true); + + if (ret.isNull()) + return QMessageBox::standardIcon(icon); + else + return ret; +} + +K3bMultiChoiceDialog::K3bMultiChoiceDialog( const QString& caption, + const QString& text, + QMessageBox::Icon icon, + QWidget* parent, const char* name ) + : KDialog( parent, name ) +{ + d = new Private(); + d->mapper = new QSignalMapper( this ); + connect( d->mapper, SIGNAL(mapped(int)), this, SLOT(done(int)) ); + + setCaption( caption ); + + QGridLayout* mainGrid = new QGridLayout( this ); + mainGrid->setSpacing( spacingHint() ); + mainGrid->setMargin( marginHint() ); + + QHBox* contents = new QHBox( this ); + contents->setSpacing( KDialog::spacingHint()*2 ); + contents->setMargin( 0 ); + + QLabel* pixLabel = new QLabel( contents ); + pixLabel->setPixmap( themedMessageBoxIcon( icon ) ); + pixLabel->setScaledContents( false ); + QLabel* label = new K3bRichTextLabel( text, contents ); + contents->setStretchFactor( label, 1 ); + + d->buttonLayout = new QHBoxLayout; + d->buttonLayout->setSpacing( spacingHint() ); + d->buttonLayout->setMargin( 0 ); + + mainGrid->addMultiCellWidget( contents, 0, 0, 0, 2 ); + mainGrid->addMultiCellWidget( K3bStdGuiItems::horizontalLine( this ), 1, 1, 0, 2 ); + mainGrid->addLayout( d->buttonLayout, 2, 1 ); + + mainGrid->setColStretch( 0, 1 ); + mainGrid->setColStretch( 2, 1 ); + mainGrid->setRowStretch( 0, 1 ); +} + + +K3bMultiChoiceDialog::~K3bMultiChoiceDialog() +{ + delete d; +} + + +int K3bMultiChoiceDialog::addButton( const KGuiItem& b ) +{ + KPushButton* button = new KPushButton( b, this ); + d->buttonLayout->add( button ); + d->buttons.append(button); + d->mapper->setMapping( button, d->buttons.count() ); + connect( button, SIGNAL(clicked()), d->mapper, SLOT(map()) ); + return d->buttons.count(); +} + + +void K3bMultiChoiceDialog::slotButtonClicked( int code ) +{ + d->buttonClicked = true; + done( code ); +} + + +int K3bMultiChoiceDialog::exec() +{ + d->buttonClicked = false; + return KDialog::exec(); +} + + +void K3bMultiChoiceDialog::closeEvent( QCloseEvent* e ) +{ + // make sure the dialog can only be closed by the buttons + // otherwise we may get an undefined return value in exec + + if( d->buttonClicked ) + KDialog::closeEvent( e ); + else + e->ignore(); +} + + +int K3bMultiChoiceDialog::choose( const QString& caption, + const QString& text, + QMessageBox::Icon icon, + QWidget* parent, + const char* name, + int buttonCount, + const KGuiItem& b1, + const KGuiItem& b2, + const KGuiItem& b3, + const KGuiItem& b4, + const KGuiItem& b5, + const KGuiItem& b6 ) +{ + K3bMultiChoiceDialog dlg( caption, text, icon, parent, name ); + dlg.addButton( b1 ); + if( buttonCount > 1 ) + dlg.addButton( b2 ); + if( buttonCount > 2 ) + dlg.addButton( b3 ); + if( buttonCount > 3 ) + dlg.addButton( b4 ); + if( buttonCount > 4 ) + dlg.addButton( b5 ); + if( buttonCount > 5 ) + dlg.addButton( b6 ); + + return dlg.exec(); +} + + +#include "k3bmultichoicedialog.moc" diff --git a/libk3b/tools/k3bmultichoicedialog.h b/libk3b/tools/k3bmultichoicedialog.h new file mode 100644 index 0000000..f293fef --- /dev/null +++ b/libk3b/tools/k3bmultichoicedialog.h @@ -0,0 +1,73 @@ +/* + * + * $Id: k3bmultichoicedialog.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_MULTI_CHOICE_DIALOG_H_ +#define _K3B_MULTI_CHOICE_DIALOG_H_ + +#include +#include +#include "k3b_export.h" + +#include + + +class QCloseEvent; + +class LIBK3B_EXPORT K3bMultiChoiceDialog : public KDialog +{ + Q_OBJECT + + public: + K3bMultiChoiceDialog( const QString& caption, + const QString& text, + QMessageBox::Icon = QMessageBox::Information, + QWidget* parent = 0, const char* name = 0 ); + ~K3bMultiChoiceDialog(); + + /** + * Adds a new button. returns it's number starting at 1. + */ + int addButton( const KGuiItem& ); + + static int choose( const QString& caption, + const QString& text, + QMessageBox::Icon = QMessageBox::Information, + QWidget* parent = 0, + const char* name = 0, + int buttonCount = 2, + const KGuiItem& b1 = KStdGuiItem::yes(), + const KGuiItem& b2 = KStdGuiItem::no(), + const KGuiItem& b3 = KStdGuiItem::no(), + const KGuiItem& b4 = KStdGuiItem::no(), + const KGuiItem& b5 = KStdGuiItem::no(), + const KGuiItem& b6 = KStdGuiItem::no() ); + + public slots: + /** + * returnes the number of the clicked button starting at 1. + */ + int exec(); + + private slots: + void slotButtonClicked( int ); + + private: + void closeEvent( QCloseEvent* ); + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bpipe.cpp b/libk3b/tools/k3bpipe.cpp new file mode 100644 index 0000000..6f15915 --- /dev/null +++ b/libk3b/tools/k3bpipe.cpp @@ -0,0 +1,79 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bpipe.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + + +K3bPipe::K3bPipe() +{ + m_fd[0] = m_fd[1] = -1; +} + + +K3bPipe::~K3bPipe() +{ + close(); +} + + +bool K3bPipe::open() +{ + close(); + + if( ::socketpair( AF_UNIX, SOCK_STREAM, 0, m_fd ) == 0 ) { + fcntl( m_fd[0], F_SETFD, FD_CLOEXEC ); + fcntl( m_fd[1], F_SETFD, FD_CLOEXEC ); + return true; + } + else { + kdDebug() << "(K3bPipe) failed to setup socket pair." << endl; + return false; + } +} + + +void K3bPipe::closeIn() +{ + if( m_fd[1] != -1 ) { + ::close( m_fd[1] ); + m_fd[1] = -1; + } +} + + +void K3bPipe::closeOut() +{ + if( m_fd[0] != -1 ) { + ::close( m_fd[0] ); + m_fd[0] = -1; + } +} + + +void K3bPipe::close() +{ + closeIn(); + closeOut(); +} diff --git a/libk3b/tools/k3bpipe.h b/libk3b/tools/k3bpipe.h new file mode 100644 index 0000000..fba3455 --- /dev/null +++ b/libk3b/tools/k3bpipe.h @@ -0,0 +1,60 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_PIPE_H_ +#define _K3B_PIPE_H_ + +#include "k3b_export.h" + +/** + * The K3bPipe class represents a file descriptor pair + * which can for example be used to connect two processes + */ +class LIBK3B_EXPORT K3bPipe +{ + public: + /** + * Creates a closed pipe object + */ + K3bPipe(); + + /** + * The destructor takes care of closing the pipe + */ + ~K3bPipe(); + + /** + * Open the pipe. This creates a file descriptor pair + * which can be accessed using the in() and out() + * methods. + */ + bool open(); + + /** + * Calls both closeIn() and closeOut() + */ + void close(); + + void closeIn(); + void closeOut(); + + int in() const { return m_fd[1]; } + int out() const { return m_fd[0]; } + + private: + int m_fd[2]; +}; + +#endif diff --git a/libk3b/tools/k3bprogressdialog.cpp b/libk3b/tools/k3bprogressdialog.cpp new file mode 100644 index 0000000..69a81f5 --- /dev/null +++ b/libk3b/tools/k3bprogressdialog.cpp @@ -0,0 +1,107 @@ +/* + * + * $Id: k3bprogressdialog.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bprogressdialog.h" + +#include + +#include +#include +#include +#include +#include + +#include +#include + + +K3bProgressDialog::K3bProgressDialog( const QString& text, + QWidget* parent, + const QString& caption, + const char* name ) + : KDialogBase( parent, name, true, caption, Cancel|Ok, Ok, true ) +{ + QFrame* main = makeMainWidget(); + QGridLayout* mainLayout = new QGridLayout( main ); + mainLayout->setMargin( marginHint() ); + mainLayout->setSpacing( spacingHint() ); + + m_label = new QLabel( text, main ); + m_stack = new QWidgetStack( main ); + m_progressBar = new KProgress( m_stack ); + m_busyWidget = new K3bBusyWidget( m_stack ); + m_stack->addWidget( m_progressBar ); + m_stack->addWidget( m_busyWidget ); + + mainLayout->addWidget( m_label, 0, 0 ); + mainLayout->addWidget( m_stack, 1, 0 ); + + showButtonOK( false ); +} + + +K3bProgressDialog::~K3bProgressDialog() +{} + + +int K3bProgressDialog::exec( bool progress ) +{ + if( progress ) + m_stack->raiseWidget( m_progressBar ); + else + m_stack->raiseWidget( m_busyWidget ); + + m_busyWidget->showBusy( !progress ); + + actionButton( Cancel )->setEnabled(true); + + return KDialogBase::exec(); +} + + +void K3bProgressDialog::setText( const QString& text ) +{ + m_label->setText( text ); +} + + +void K3bProgressDialog::slotFinished( bool success ) +{ + m_busyWidget->showBusy( false ); + + showButtonOK( true ); + showButtonCancel( false ); + + if( success ) + m_label->setText( i18n("Disk successfully erased. Please reload the disk.") ); + else + m_label->setText( i18n("K3b was unable to erase the disk.") ); +} + + +void K3bProgressDialog::slotCancel() +{ + emit cancelClicked(); + // we simply forbid to click cancel twice + actionButton( Cancel )->setEnabled(false); +} + + +void K3bProgressDialog::setProgress( int p ) +{ + m_progressBar->setProgress( p ); +} + +#include "k3bprogressdialog.moc" diff --git a/libk3b/tools/k3bprogressdialog.h b/libk3b/tools/k3bprogressdialog.h new file mode 100644 index 0000000..32a0544 --- /dev/null +++ b/libk3b/tools/k3bprogressdialog.h @@ -0,0 +1,63 @@ +/* + * + * $Id: k3bprogressdialog.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_PROGRESS_DIALOG_H_ +#define _K3B_PROGRESS_DIALOG_H_ + +#include +#include "k3b_export.h" + +class K3bBusyWidget; +class QLabel; +class KProgress; +class QWidgetStack; + + +/** + * A progressdialog which displays a line of text and a progress + * bar or a moving dot for tasks that do not provide any progress + * information. + */ +class LIBK3B_EXPORT K3bProgressDialog : public KDialogBase +{ + Q_OBJECT + + public: + K3bProgressDialog( const QString& text = QString::null, + QWidget* parent = 0, + const QString& caption = QString::null, + const char* name = 0 ); + ~K3bProgressDialog(); + + int exec( bool showProgress ); + + public slots: + void setText( const QString& ); + void slotFinished( bool success ); + void setProgress( int p ); + + private slots: + void slotCancel(); + + private: + QLabel* m_label; + QWidgetStack* m_stack; + K3bBusyWidget* m_busyWidget; + KProgress* m_progressBar; +}; + + +#endif diff --git a/libk3b/tools/k3bpushbutton.cpp b/libk3b/tools/k3bpushbutton.cpp new file mode 100644 index 0000000..11425ad --- /dev/null +++ b/libk3b/tools/k3bpushbutton.cpp @@ -0,0 +1,136 @@ +/* + * + * $Id: k3bpushbutton.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bpushbutton.h" + +#include +#include +#include + +#include +#include + + + +class K3bPushButton::Private +{ +public: + Private() + : popupTimer(0) { + } + + QTimer* popupTimer; + QPoint mousePressPos; +}; + + + +K3bPushButton::K3bPushButton( QWidget* parent, const char* name ) + : KPushButton( parent, name ) +{ + d = new Private(); + installEventFilter(this); +} + + +K3bPushButton::K3bPushButton( const QString& text, QWidget* parent, const char* name ) + : KPushButton( text, parent, name ) +{ + d = new Private(); + installEventFilter(this); +} + + +K3bPushButton::K3bPushButton( const QIconSet& icon, const QString& text, + QWidget* parent, const char* name ) + : KPushButton( icon, text, parent, name ) +{ + d = new Private(); + installEventFilter(this); +} + + +K3bPushButton::K3bPushButton( const KGuiItem& item, QWidget* parent, const char* name ) + : KPushButton( item, parent, name ) +{ + d = new Private(); + installEventFilter(this); +} + + +K3bPushButton::~K3bPushButton() +{ + delete d; +} + + +void K3bPushButton::setDelayedPopupMenu( QPopupMenu* popup ) +{ + if( !d->popupTimer ) { + d->popupTimer = new QTimer( this ); + connect( d->popupTimer, SIGNAL(timeout()), this, SLOT(slotDelayedPopup()) ); + } + + setPopup( popup ); + + // we need to do the popup handling ourselves so we cheat a little + // QPushButton connects a popup slot to the pressed signal which we disconnect here + disconnect( this ); +} + + +bool K3bPushButton::eventFilter( QObject* o, QEvent* ev ) +{ + if( dynamic_cast(o) == this ) { + + // Popup the menu when the left mousebutton is pressed and the mouse + // is moved by a small distance. + if( popup() ) { + if( ev->type() == QEvent::MouseButtonPress ) { + QMouseEvent* mev = static_cast(ev); + d->mousePressPos = mev->pos(); + d->popupTimer->start( QApplication::startDragTime() ); + } + else if( ev->type() == QEvent::MouseMove ) { + QMouseEvent* mev = static_cast(ev); + if( ( mev->pos() - d->mousePressPos).manhattanLength() > KGlobalSettings::dndEventDelay() ) { + d->popupTimer->stop(); + slotDelayedPopup(); + return true; + } + } + } + } + + return KPushButton::eventFilter( o, ev ); +} + + +void K3bPushButton::slotDelayedPopup() +{ + d->popupTimer->stop(); + + if( isDown() ) { + // popup the menu. + // this has been taken from the QPushButton code + if( mapToGlobal( QPoint( 0, rect().bottom() ) ).y() + popup()->sizeHint().height() <= qApp->desktop()->height() ) + popup()->exec( mapToGlobal( rect().bottomLeft() ) ); + else + popup()->exec( mapToGlobal( rect().topLeft() - QPoint( 0, popup()->sizeHint().height() ) ) ); + setDown( false ); + } +} + +#include "k3bpushbutton.moc" diff --git a/libk3b/tools/k3bpushbutton.h b/libk3b/tools/k3bpushbutton.h new file mode 100644 index 0000000..1369af3 --- /dev/null +++ b/libk3b/tools/k3bpushbutton.h @@ -0,0 +1,75 @@ +/* + * + * $Id: k3bpushbutton.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2004-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_PUSH_BUTTON_H_ +#define _K3B_PUSH_BUTTON_H_ + + +#include +#include "k3b_export.h" + +/** + * A pushbutton with delayed popu pmenu support just like the KToolBarButton + */ +class LIBK3B_EXPORT K3bPushButton : public KPushButton +{ + Q_OBJECT + + public: + /** + * Default constructor. + */ + K3bPushButton( QWidget* parent = 0, const char* name = 0 ); + + /** + * Constructor, that sets the button-text to @p text + */ + K3bPushButton( const QString& text, QWidget* parent = 0, const char* name = 0 ); + + /** + * Constructor, that sets an icon and the button-text to @p text + */ + K3bPushButton( const QIconSet& icon, const QString& text, + QWidget* parent = 0, const char* name = 0 ); + + /** + * Constructor that takes a KGuiItem for the text, the icon, the tooltip + * and the what's this help + */ + K3bPushButton( const KGuiItem& item, QWidget* parent = 0, const char* name = 0 ); + + /** + * Destructs the button. + */ + ~K3bPushButton(); + + /** + * The popup menu will show if the button is pressed down for about half a second + * or if the mouse is moved while pressed just like the KToolBarButton. + */ + void setDelayedPopupMenu( QPopupMenu* ); + + protected: + virtual bool eventFilter( QObject*, QEvent* ); + + private slots: + void slotDelayedPopup(); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bradioaction.cpp b/libk3b/tools/k3bradioaction.cpp new file mode 100644 index 0000000..08fbece --- /dev/null +++ b/libk3b/tools/k3bradioaction.cpp @@ -0,0 +1,94 @@ +/* + * + * $Id: k3bradioaction.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bradioaction.h" + +#include + +K3bRadioAction::K3bRadioAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) + : KToggleAction( text, cut, parent, name ), + m_alwaysEmit(false) +{ +} + +K3bRadioAction::K3bRadioAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KToggleAction( text, cut, receiver, slot, parent, name ), + m_alwaysEmit(false) +{ +} + +K3bRadioAction::K3bRadioAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KToggleAction( text, pix, cut, parent, name ), + m_alwaysEmit(false) +{ +} + +K3bRadioAction::K3bRadioAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KToggleAction( text, pix, cut, parent, name ), + m_alwaysEmit(false) +{ +} + +K3bRadioAction::K3bRadioAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KToggleAction( text, pix, cut, receiver, slot, parent, name ), + m_alwaysEmit(false) +{ +} + +K3bRadioAction::K3bRadioAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KToggleAction( text, pix, cut, receiver, slot, parent, name ), + m_alwaysEmit(false) +{ +} + +K3bRadioAction::K3bRadioAction( QObject* parent, const char* name ) + : KToggleAction( parent, name ), + m_alwaysEmit(false) +{ +} + +void K3bRadioAction::slotActivated() +{ + if( isChecked() ) { + if( m_alwaysEmit ) + emit activated(); + + const QObject *senderObj = sender(); + + if ( !senderObj || !::qt_cast( senderObj ) ) + return; + + const_cast( static_cast( senderObj ) )->on( true ); + + return; + } + + KToggleAction::slotActivated(); +} + +#include "k3bradioaction.moc" diff --git a/libk3b/tools/k3bradioaction.h b/libk3b/tools/k3bradioaction.h new file mode 100644 index 0000000..104b598 --- /dev/null +++ b/libk3b/tools/k3bradioaction.h @@ -0,0 +1,122 @@ +/* + * + * $Id: k3bradioaction.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_RADIO_ACTION_H_ +#define _K3B_RADIO_ACTION_H_ + +#include +#include "k3b_export.h" + +/** + * This differs from KRadioAction only in the boolean + * flag which says if it should always emit the signals + * even if it was checked twice. + * + * Docu copied from kdelibs + */ +class LIBK3B_EXPORT K3bRadioAction : public KToggleAction +{ + Q_OBJECT + + public: + /** + * Constructs a radio action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + K3bRadioAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + K3bRadioAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + K3bRadioAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + K3bRadioAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + K3bRadioAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + K3bRadioAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + K3bRadioAction( QObject* parent = 0, const char* name = 0 ); + + /** + * @param b if true the action will always emit the activated signal + * even if the toggled state did not change. The default is false. + * which is the same behaviour as KRadioAction + */ + void setAlwaysEmitActivated( bool b ) { m_alwaysEmit = b; } + + protected: + virtual void slotActivated(); + + private: + bool m_alwaysEmit; +}; + +#endif diff --git a/libk3b/tools/k3brichtextlabel.cpp b/libk3b/tools/k3brichtextlabel.cpp new file mode 100644 index 0000000..747bba1 --- /dev/null +++ b/libk3b/tools/k3brichtextlabel.cpp @@ -0,0 +1,109 @@ +/* + * + * $Id: k3brichtextlabel.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Waldo Bastian + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3brichtextlabel.h" + +#include +#include +#include + +#include + +static QString qrichtextify( const QString& text ) +{ + if ( text.isEmpty() || text[0] == '<' ) + return text; + + QStringList lines = QStringList::split('\n', text); + for(QStringList::Iterator it = lines.begin(); it != lines.end(); ++it) + { + *it = QStyleSheet::convertFromPlainText( *it, QStyleSheetItem::WhiteSpaceNormal ); + } + + return lines.join(QString::null); +} + +K3bRichTextLabel::K3bRichTextLabel( const QString &text , QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + m_defaultWidth = QMIN(400, KGlobalSettings::desktopGeometry(this).width()*2/5); + setAlignment( Qt::WordBreak ); + setText(text); +} + +K3bRichTextLabel::K3bRichTextLabel( QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + m_defaultWidth = QMIN(400, KGlobalSettings::desktopGeometry(this).width()*2/5); + setAlignment( Qt::WordBreak ); +} + +void K3bRichTextLabel::setDefaultWidth(int defaultWidth) +{ + m_defaultWidth = defaultWidth; + updateGeometry(); +} + +QSizePolicy K3bRichTextLabel::sizePolicy() const +{ + return QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum, false); +} + +QSize K3bRichTextLabel::minimumSizeHint() const +{ + QString qt_text = qrichtextify( text() ); + int pref_width = 0; + int pref_height = 0; + QSimpleRichText rt(qt_text, font()); + pref_width = m_defaultWidth; + rt.setWidth(pref_width); + int used_width = rt.widthUsed(); + if (used_width <= pref_width) + { + while(true) + { + int new_width = (used_width * 9) / 10; + rt.setWidth(new_width); + int new_height = rt.height(); + if (new_height > pref_height) + break; + used_width = rt.widthUsed(); + if (used_width > new_width) + break; + } + pref_width = used_width; + } + else + { + if (used_width > (pref_width *2)) + pref_width = pref_width *2; + else + pref_width = used_width; + } + + return QSize(pref_width, rt.height()); +} + +QSize K3bRichTextLabel::sizeHint() const +{ + return minimumSizeHint(); +} + +void K3bRichTextLabel::setText( const QString &text ) { + QLabel::setText(text); +} + +void K3bRichTextLabel::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +#include "k3brichtextlabel.moc" diff --git a/libk3b/tools/k3brichtextlabel.h b/libk3b/tools/k3brichtextlabel.h new file mode 100644 index 0000000..0a25395 --- /dev/null +++ b/libk3b/tools/k3brichtextlabel.h @@ -0,0 +1,62 @@ +/* + * + * $Id: k3brichtextlabel.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Waldo Bastian + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3BRICHTEXTLABEL_H +#define K3BRICHTEXTLABEL_H + +#include + +#include + +/** + * @short A replacement for QLabel that supports richtext and proper layout management + * + * @author Waldo Bastian + */ + +/* + * QLabel + */ +class LIBK3B_EXPORT K3bRichTextLabel : public QLabel { + Q_OBJECT + +public: + /** + * Default constructor. + */ + K3bRichTextLabel( QWidget *parent, const char *name = 0 ); + K3bRichTextLabel( const QString &text, QWidget *parent, const char *name = 0 ); + + int defaultWidth() const { return m_defaultWidth; } + void setDefaultWidth(int defaultWidth); + + virtual QSize minimumSizeHint() const; + virtual QSize sizeHint() const; + QSizePolicy sizePolicy() const; + +public slots: + void setText( const QString & ); + +protected: + int m_defaultWidth; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class K3bRichTextLabelPrivate; + K3bRichTextLabelPrivate *d; +}; + +#endif // K3BRICHTEXTLABEL_H diff --git a/libk3b/tools/k3bsignalwaiter.cpp b/libk3b/tools/k3bsignalwaiter.cpp new file mode 100644 index 0000000..fcee2e0 --- /dev/null +++ b/libk3b/tools/k3bsignalwaiter.cpp @@ -0,0 +1,62 @@ +/* + * + * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bsignalwaiter.h" +#include "k3bjob.h" + +#include +#include + + +K3bSignalWaiter::K3bSignalWaiter() + : QObject(), + m_inLoop(true) +{ +} + + +K3bSignalWaiter::~K3bSignalWaiter() +{ +} + + +void K3bSignalWaiter::waitForSignal( QObject* o, const char* signal ) +{ + K3bSignalWaiter w; + connect( o, signal, + &w, SLOT(slotSignal()) ); + + QApplication::eventLoop()->enterLoop(); +} + + +void K3bSignalWaiter::waitForJob( K3bJob* job ) +{ + if( !job->active() ) + return; + + waitForSignal( job, SIGNAL(finished(bool)) ); +} + + +void K3bSignalWaiter::slotSignal() +{ + if( m_inLoop ) { + m_inLoop = false; + QApplication::eventLoop()->exitLoop(); + } +} + +#include "k3bsignalwaiter.moc" diff --git a/libk3b/tools/k3bsignalwaiter.h b/libk3b/tools/k3bsignalwaiter.h new file mode 100644 index 0000000..19876b4 --- /dev/null +++ b/libk3b/tools/k3bsignalwaiter.h @@ -0,0 +1,51 @@ +/* + * + * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_SIGNAL_WAITER_H_ +#define _K3B_SIGNAL_WAITER_H_ + +#include + +#include + +class K3bJob; + +class K3bSignalWaiter : public QObject +{ + Q_OBJECT + + public: + /** + * Use this to syncroneously wait for a signal. + */ + LIBK3B_EXPORT static void waitForSignal( QObject* o, const char* signal ); + + /** + * Use this to syncroneously wait for a job to finish. + * If the job is not running at all this returns immedeately. + */ + LIBK3B_EXPORT static void waitForJob( K3bJob* job ); + + private slots: + void slotSignal(); + + private: + K3bSignalWaiter(); + ~K3bSignalWaiter(); + + bool m_inLoop; +}; + +#endif diff --git a/libk3b/tools/k3bstdguiitems.cpp b/libk3b/tools/k3bstdguiitems.cpp new file mode 100644 index 0000000..8a6ab00 --- /dev/null +++ b/libk3b/tools/k3bstdguiitems.cpp @@ -0,0 +1,215 @@ +/* + * + * $Id: k3bstdguiitems.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bstdguiitems.h" + +#include +#include +#include +#include +#include +#include + +#include + + +QCheckBox* K3bStdGuiItems::simulateCheckbox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Simulate"), parent, name ); + QWhatsThis::add( c, i18n("

If this option is checked K3b will perform all writing steps with the " + "laser turned off." + "

This is useful, for example, to test a higher writing speed " + "or whether your system is able to write on-the-fly." + "

Caution: DVD+R(W) does not support simulated writing.") ); + QToolTip::add( c, i18n("Only simulate the writing process") ); + return c; +} + +QCheckBox* K3bStdGuiItems::daoCheckbox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Disk at once"), parent, name ); + QWhatsThis::add( c, i18n("

If this option is checked, K3b will write the CD in 'disk at once' mode as " + "compared to 'track at once' (TAO)." + "

It is always recommended to use DAO where possible." + "

Caution: Track pregaps with a length other than 2 seconds are only supported " + "in DAO mode.") ); + QToolTip::add( c, i18n("Write in disk at once mode") ); + return c; +} + +QCheckBox* K3bStdGuiItems::burnproofCheckbox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Use Burnfree"), parent, name ); + QToolTip::add( c, i18n("Enable Burnfree (or Just Link) to avoid buffer underruns") ); + QWhatsThis::add( c, i18n("

If this option is checked, K3b enables Burnfree " + "(or Just Link). This is " + "a feature of the CD writer which avoids buffer underruns." + "

Without burnfree, if the writer cannot get any more " + "data a buffer underrun would occurs, since the writer needs " + "a constant stream of data to write the CD." + "

With burnfree the writer can mark the current " + "position of the laser and get back to it when the buffer is filled again;" + "but, since this means having little data gaps on the CD, it is " + "highly recommended to always choose an appropriate writing " + "speed to prevent the usage of burnfree, especially for audio CDs " + "(in the worst case one would hear the gap)." + "

Burnfree was formerly known as Burnproof, " + "but has since been renamed when it became part of the MMC standard.") ); + return c; +} + +QCheckBox* K3bStdGuiItems::onlyCreateImagesCheckbox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Only create image"), parent, name ); + QWhatsThis::add( c, i18n("

If this option is checked, K3b will only create an " + "image and not do any actual writing." + "

The image can later be written to a CD/DVD with most current writing " + "programs (including K3b of course).") ); + QToolTip::add( c, i18n("Only create an image") ); + return c; +} + +QCheckBox* K3bStdGuiItems::createCacheImageCheckbox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Create image"), parent, name ); + QWhatsThis::add( c, i18n("

If this option is checked, K3b will create an image before writing " + "the files to the CD/DVD. Otherwise the data will be written on-the-fly, " + "i.e. no intermediate image will be created." + "

Caution: Although writing on-the-fly should work on most systems, make sure " + "the data is sent to the writer fast enough.") + + i18n("

It is recommended to try a simulation first.") ); + QToolTip::add( c, i18n("Cache the data to be written on the harddisk") ); + return c; +} + +QCheckBox* K3bStdGuiItems::removeImagesCheckbox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Remove image"), parent, name ); + QWhatsThis::add( c, i18n("

If this option is checked, K3b will remove any created images after the " + "writing has finished." + "

Uncheck this if you want to keep the images.") ); + QToolTip::add( c, i18n("Remove images from disk when finished") ); + return c; +} + +QCheckBox* K3bStdGuiItems::onTheFlyCheckbox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("On the fly"), parent, name ); + QWhatsThis::add( c, i18n("

If this option is checked, K3b will not create an image first but write " + "the files directly to the CD/DVD." + "

Caution: Although this should work on most systems, make sure " + "the data is sent to the writer fast enough.") + + i18n("

It is recommended to try a simulation first.") ); + QToolTip::add( c, i18n("Write files directly to CD/DVD without creating an image") ); + return c; +} + +QCheckBox* K3bStdGuiItems::cdTextCheckbox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Write CD-TEXT"), parent, name ); + QToolTip::add( c, i18n("Create CD-TEXT entries") ); + QWhatsThis::add( c, i18n("

If this option is checked K3b uses some otherwise-unused space on the audio " + "CD to store additional information, like the artist or the CD title." + "

CD-TEXT is an extension to the audio CD standard introduced by Sony." + "

CD-TEXT will only be usable on CD players that support this extension " + "(mostly car CD players)." + "

Since a CD-TEXT-enhanced CDs will work in any CD player it is never a bad " + "idea to enable this (if you specify CD-TEXT data).") ); + return c; +} + + +QComboBox* K3bStdGuiItems::paranoiaModeComboBox( QWidget* parent, const char* name ) +{ + QComboBox* c = new QComboBox( parent, name ); + c->insertItem( "0" ); + c->insertItem( "1" ); + c->insertItem( "2" ); + c->insertItem( "3" ); + c->setCurrentItem( 3 ); + QToolTip::add( c, i18n("Set the paranoia level for reading audio CDs") ); + QWhatsThis::add( c, i18n("

Sets the correction mode for digital audio extraction." + "

  • 0: No checking, data is copied directly from the drive. " + "
  • 1: Perform overlapped reading to avoid jitter.
  • " + "
  • 2: Like 1 but with additional checks of the read audio data.
  • " + "
  • 3: Like 2 but with additional scratch detection and repair.
" + "

The extraction speed reduces from 0 to 3.") ); + return c; +} + + +QCheckBox* K3bStdGuiItems::startMultisessionCheckBox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Start multisession CD"), parent, name ); + QToolTip::add( c, i18n("Do not close the disk to allow additional sessions to be added later") ); + QWhatsThis::add( c, i18n("

If this option is checked K3b will not close the CD, and will write " + "a temporary table of contents.

" + "

This allows further sessions to be appended to the CD later.

") ); + return c; +} + + +QCheckBox* K3bStdGuiItems::normalizeCheckBox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Normalize volume levels"), parent, name ); + QToolTip::add( c, i18n("Adjust the volume levels of all tracks") ); + QWhatsThis::add( c, i18n("

If this option is checked K3b will adjust the volume of all tracks " + "to a standard level. This is useful for things like creating mixes, " + "where different recording levels on different albums can cause the volume " + "to vary greatly from song to song." + "

Be aware that K3b currently does not support normalizing when writing " + "on the fly.") ); + return c; +} + + +QCheckBox* K3bStdGuiItems::verifyCheckBox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Verify written data"), parent, name ); + QToolTip::add( c, i18n("Compare original with written data") ); + QWhatsThis::add( c, i18n("

If this option is checked, then after successfully " + "writing the disk K3b will compare the original source data " + "with the written data to verify that the disk has been written " + "correctly.") ); + return c; +} + + +QCheckBox* K3bStdGuiItems::ignoreAudioReadErrorsCheckBox( QWidget* parent, const char* name ) +{ + QCheckBox* c = new QCheckBox( i18n("Ignore read errors"), parent, name ); + QToolTip::add( c, i18n("Skip unreadable audio sectors") ); + QWhatsThis::add( c, i18n("

If this option is checked and K3b is not able to read an " + "audio sector from the source CD it will be replaced with zeros " + "on the resulting copy." + "

Since audio CD Player are able to interpolate small errors " + "in the data it is no problem to let K3b skip unreadable sectors.") ); + return c; +} + + +QFrame* K3bStdGuiItems::horizontalLine( QWidget* parent, const char* name ) +{ + QFrame* line = new QFrame( parent, name ); + line->setFrameStyle( QFrame::HLine | QFrame::Sunken ); + return line; +} + +QFrame* K3bStdGuiItems::verticalLine( QWidget* parent, const char* name ) +{ + QFrame* line = new QFrame( parent, name ); + line->setFrameStyle( QFrame::VLine | QFrame::Sunken ); + return line; +} diff --git a/libk3b/tools/k3bstdguiitems.h b/libk3b/tools/k3bstdguiitems.h new file mode 100644 index 0000000..e118b6a --- /dev/null +++ b/libk3b/tools/k3bstdguiitems.h @@ -0,0 +1,45 @@ +/* + * + * $Id: k3bstdguiitems.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_STD_GUIITEMS_H +#define K3B_STD_GUIITEMS_H +#include "k3b_export.h" + +class QWidget; +class QCheckBox; +class QComboBox; +class QFrame; + + +namespace K3bStdGuiItems +{ + LIBK3B_EXPORT QCheckBox* simulateCheckbox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* daoCheckbox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* burnproofCheckbox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* onlyCreateImagesCheckbox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* createCacheImageCheckbox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* removeImagesCheckbox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* onTheFlyCheckbox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* cdTextCheckbox( QWidget* parent = 0, const char* name = 0); + LIBK3B_EXPORT QComboBox* paranoiaModeComboBox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* startMultisessionCheckBox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* normalizeCheckBox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* verifyCheckBox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QCheckBox* ignoreAudioReadErrorsCheckBox( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QFrame* horizontalLine( QWidget* parent = 0, const char* name = 0 ); + LIBK3B_EXPORT QFrame* verticalLine( QWidget* parent = 0, const char* name = 0 ); +} + +#endif diff --git a/libk3b/tools/k3bstringutils.cpp b/libk3b/tools/k3bstringutils.cpp new file mode 100644 index 0000000..198bb9e --- /dev/null +++ b/libk3b/tools/k3bstringutils.cpp @@ -0,0 +1,111 @@ +/* + * + * $Id: k3bstringutils.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bstringutils.h" + +#include + +#include + + +QString K3b::cutToWidth( const QFontMetrics& fm, const QString& fullText, int cutWidth ) +{ + QString squeezedText = "..."; + int squeezedWidth = fm.width(squeezedText); + int textWidth = fm.width(fullText); + + if( textWidth <= cutWidth ) { + return fullText; + } + + if( fm.width(fullText.right(1) + "..." ) > cutWidth ) { + kdDebug() << "(K3b::cutToWidth) not able to cut text to " << cutWidth << "!" << endl; + return fullText.right(1) + "..."; + } + + // estimate how many letters we can add to the dots + int letters = fullText.length() * (cutWidth - squeezedWidth) / textWidth; + squeezedText = fullText.left(letters) + "..."; + squeezedWidth = fm.width(squeezedText); + + if (squeezedWidth < cutWidth) { + // we estimated too short + // add letters while text < label + do { + letters++; + squeezedText = fullText.left(letters) + "..."; + squeezedWidth = fm.width(squeezedText); + } while (squeezedWidth < cutWidth); + letters--; + squeezedText = fullText.left(letters) + "..."; + } else if (squeezedWidth > cutWidth) { + // we estimated too long + // remove letters while text > label + do { + letters--; + squeezedText = fullText.left(letters) + "..."; + squeezedWidth = fm.width(squeezedText); + } while (squeezedWidth > cutWidth); + } + + return squeezedText; +} + + +// from KSqueezedTextLabel +QString K3b::squeezeTextToWidth( const QFontMetrics& fm, const QString& fullText, int cutWidth ) +{ + int textWidth = fm.width(fullText); + if (textWidth > cutWidth) { + // start with the dots only + QString squeezedText = "..."; + int squeezedWidth = fm.width(squeezedText); + + // estimate how many letters we can add to the dots on both sides + int letters = fullText.length() * (cutWidth - squeezedWidth) / textWidth / 2; + if (cutWidth < squeezedWidth) letters=1; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + + if (squeezedWidth < cutWidth) { + // we estimated too short + // add letters while text < label + do { + letters++; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + } while (squeezedWidth < cutWidth); + letters--; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + } + else if (squeezedWidth > cutWidth) { + // we estimated too long + // remove letters while text > label + do { + letters--; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + } while (letters > 2 && squeezedWidth > cutWidth); + } + + if (letters == 2) + kdDebug() << "(K3b::squeezeTextToWidth) WARNING: unable to squeeze text to width " + << cutWidth << endl; + + return squeezedText; + } + else + return fullText; +} diff --git a/libk3b/tools/k3bstringutils.h b/libk3b/tools/k3bstringutils.h new file mode 100644 index 0000000..05cfd32 --- /dev/null +++ b/libk3b/tools/k3bstringutils.h @@ -0,0 +1,39 @@ +/* + * + * $Id: k3bstringutils.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_STRING_UTILS_H_ +#define _K3B_STRING_UTILS_H_ + +#include + +class QFontMetrics; + +namespace K3b +{ + /** + * Cuts the text at the end. + * Example: "some long text" -> "some lo..." + */ + QString cutToWidth( const QFontMetrics&, const QString&, int ); + + /** + * squeezes the text. + * Example: "some long text" -> "some...ext" + */ + QString squeezeTextToWidth( const QFontMetrics& fm, const QString& fullText, int cutWidth ); +} + +#endif diff --git a/libk3b/tools/k3btempfile.cpp b/libk3b/tools/k3btempfile.cpp new file mode 100644 index 0000000..635be40 --- /dev/null +++ b/libk3b/tools/k3btempfile.cpp @@ -0,0 +1,51 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3btempfile.h" + +#include +#include + + +static inline QString defaultTempDir() +{ + // we need a world-readable temp dir + + // FIXME: check if the default is world-readable +// QStringList dirs = KGlobal::dirs()->resourceDirs( "tmp" ); +// for( QStringList::const_iterator it = dirs.begin(); +// it != dirs.end(); ++it ) { +// const QString& dir = *it; + +// } + + // fallback to /tmp + return "/tmp/k3b"; +} + + +K3bTempFile::K3bTempFile( const QString& filePrefix, + const QString& fileExtension, + int mode ) + : KTempFile( filePrefix.isEmpty() ? defaultTempDir() : filePrefix, + fileExtension, + mode ) +{ +} + + +K3bTempFile::~K3bTempFile() +{ +} diff --git a/libk3b/tools/k3btempfile.h b/libk3b/tools/k3btempfile.h new file mode 100644 index 0000000..41a8756 --- /dev/null +++ b/libk3b/tools/k3btempfile.h @@ -0,0 +1,43 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_TEMP_FILE_H_ +#define _K3B_TEMP_FILE_H_ + +#include + +#include + +/** + * K3bTempFile does only change one thing over KTempFile: + * It tries to use a default temp dir which is always world-readable. + * + * This is important in the following situation: + * + * cdrecord often runs suid root. Some distributions like Mandriva + * set the default KDE temp dir to $HOME/tmp-$USER. Thus, if the home + * dir is mounted via NFS root has no read permissions htere and cdrecord + * fails to read the temp files. + */ +class LIBK3B_EXPORT K3bTempFile : public KTempFile +{ + public: + K3bTempFile( const QString& filePrefix = QString::null, + const QString& fileExtension = QString::null, + int mode = 0600 ); + ~K3bTempFile(); +}; + +#endif diff --git a/libk3b/tools/k3bthreadwidget.cpp b/libk3b/tools/k3bthreadwidget.cpp new file mode 100644 index 0000000..ea82101 --- /dev/null +++ b/libk3b/tools/k3bthreadwidget.cpp @@ -0,0 +1,142 @@ +/* + * + * $Id: k3bthreadwidget.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bthreadwidget.h" +#include "k3bdeviceselectiondialog.h" +#include + +#include +#include +#include + + +class K3bThreadWidget::Data +{ +public: + int id; + void* data; + QWaitCondition con; +}; + + +class K3bThreadWidget::DeviceSelectionEvent : public QCustomEvent +{ +public: + DeviceSelectionEvent( QWidget* parent, const QString& text, int id ) + : QCustomEvent( QEvent::User + 22 ), + m_parent(parent), + m_text(text), + m_id(id) { + } + + QWidget* parent() const { return m_parent; } + const QString& text() const { return m_text; } + int id() const { return m_id; } + +private: + QWidget* m_parent; + QString m_text; + int m_id; +}; + + +K3bThreadWidget* K3bThreadWidget::s_instance = 0; + + +K3bThreadWidget::K3bThreadWidget() + : QObject(), + m_idCounter(1) +{ + m_dataMap.setAutoDelete(true); + s_instance = this; +} + + +K3bThreadWidget::~K3bThreadWidget() +{ + s_instance = 0; +} + + +int K3bThreadWidget::getNewId() +{ + // create new data + Data* data = new Data; + data->id = m_idCounter++; + data->data = 0; + m_dataMap.insert( data->id, data ); + return data->id; +} + + +void K3bThreadWidget::clearId( int id ) +{ + m_dataMap.remove( id ); +} + + +K3bThreadWidget::Data* K3bThreadWidget::data( int id ) +{ + return m_dataMap[id]; +} + + +K3bThreadWidget* K3bThreadWidget::instance() +{ + if( !s_instance ) + s_instance = new K3bThreadWidget(); + return s_instance; +} + + +// static +K3bDevice::Device* K3bThreadWidget::selectDevice( QWidget* parent, + const QString& text ) +{ + // request a new data set + Data* data = K3bThreadWidget::instance()->data( K3bThreadWidget::instance()->getNewId() ); + + // inform the instance about the request + QApplication::postEvent( K3bThreadWidget::instance(), + new K3bThreadWidget::DeviceSelectionEvent( parent, text, data->id ) ); + + // wait for the result to be ready + data->con.wait(); + + K3bDevice::Device* dev = static_cast( data->data ); + + // delete the no longer needed data + K3bThreadWidget::instance()->clearId( data->id ); + + return dev; +} + + +void K3bThreadWidget::customEvent( QCustomEvent* e ) +{ + if( DeviceSelectionEvent* dse = dynamic_cast(e) ) { + // create dialog + K3bDevice::Device* dev = K3bDeviceSelectionDialog::selectDevice( dse->parent(), dse->text() ); + + // return it to the thread + Data* dat = data( dse->id() ); + dat->data = static_cast( dev ); + + // wake the thread + dat->con.wakeAll(); + } +} + +#include "k3bthreadwidget.moc" diff --git a/libk3b/tools/k3bthreadwidget.h b/libk3b/tools/k3bthreadwidget.h new file mode 100644 index 0000000..b3fedb2 --- /dev/null +++ b/libk3b/tools/k3bthreadwidget.h @@ -0,0 +1,78 @@ +/* + * + * $Id: k3bthreadwidget.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2005 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_THREAD_WIDGET_H_ +#define _K3B_THREAD_WIDGET_H_ + +#include +#include + + +class QCustomEvent; +namespace K3bDevice { + class Device; +} + +/** + * This class allows a thread other than the GUI thread to perform simple GUI + * operations. Mainly creating some simple K3b Dialogs like Device selection. + * + * Since the calling thread cannot create the K3bThreadWidget by himself there exists + * exactly one instance created by K3bCore which is used by all threads. + */ +class K3bThreadWidget : public QObject +{ + Q_OBJECT + + public: + ~K3bThreadWidget(); + + static K3bThreadWidget* instance(); + + /** + * Call this from a thread to show a device selection dialog. + */ + static K3bDevice::Device* selectDevice( QWidget* parent, + const QString& text = QString::null ); + + protected: + /** + * communication between the threads + */ + void customEvent( QCustomEvent* ); + + private: + /** + * used internally + */ + class DeviceSelectionEvent; + class Data; + + K3bThreadWidget(); + + /** + * Get unique id + */ + int getNewId(); + void clearId( int id ); + Data* data( int id ); + + int m_idCounter; + QIntDict m_dataMap; + + static K3bThreadWidget* s_instance; +}; + +#endif diff --git a/libk3b/tools/k3bthroughputestimator.cpp b/libk3b/tools/k3bthroughputestimator.cpp new file mode 100644 index 0000000..aa52478 --- /dev/null +++ b/libk3b/tools/k3bthroughputestimator.cpp @@ -0,0 +1,98 @@ +/* + * + * $Id: k3bthroughputestimator.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bthroughputestimator.h" + +#include +#include + + +class K3bThroughputEstimator::Private +{ +public: + Private() + : started(false) { + } + + QTime firstDataTime; + unsigned long firstData; + QTime lastDataTime; + unsigned long lastData; + + int lastThroughput; + + bool started; +}; + + +K3bThroughputEstimator::K3bThroughputEstimator( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + d = new Private(); +} + + +K3bThroughputEstimator::~K3bThroughputEstimator() +{ + delete d; +} + + +int K3bThroughputEstimator::average() const +{ + int msecs = d->firstDataTime.msecsTo( d->lastDataTime ); + if( msecs > 0 ) + return (int)( 1000.0*(double)(d->lastData - d->firstData)/(double)msecs); + else + return 0; +} + + +void K3bThroughputEstimator::reset() +{ + d->started = false; +} + + +void K3bThroughputEstimator::dataWritten( unsigned long data ) +{ + if( !d->started ) { + d->started = true; + d->firstData = d->lastData = data; + d->firstDataTime.start(); + d->lastDataTime.start(); + d->lastThroughput = 0; + } + else if( data > d->lastData ) { + unsigned long diff = data - d->lastData; + int msecs = d->lastDataTime.elapsed(); + + //if( msecs > 0 ) { + // down the update sequence a little bit + if( msecs > 500 ) { + d->lastData = data; + d->lastDataTime.start(); + int t = (int)(1000.0*(double)diff/(double)msecs); + if( t != d->lastThroughput ) { + d->lastThroughput = t; + emit throughput( t ); + } + } + } +} + + +#include "k3bthroughputestimator.moc" diff --git a/libk3b/tools/k3bthroughputestimator.h b/libk3b/tools/k3bthroughputestimator.h new file mode 100644 index 0000000..aed71e0 --- /dev/null +++ b/libk3b/tools/k3bthroughputestimator.h @@ -0,0 +1,57 @@ +/* + * + * $Id: k3bthroughputestimator.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_THROUGHPUT_ESTIMATOR_H_ +#define _K3B_THROUGHPUT_ESTIMATOR_H_ + +#include + + +/** + * Little helper class that allows an estimation of the current writing + * speed. Just init with @p reset() then always call @p dataWritten with + * the already written data in KB. The class will emit throughput signals + * whenever the throughput changes. + */ +class K3bThroughputEstimator : public QObject +{ + Q_OBJECT + + public: + K3bThroughputEstimator( QObject* parent = 0, const char* name = 0 ); + ~K3bThroughputEstimator(); + + int average() const; + + signals: + /** + * kb/s if differs from previous + */ + void throughput( int ); + + public slots: + void reset(); + + /** + * @param data written kb + */ + void dataWritten( unsigned long data ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3btitlelabel.cpp b/libk3b/tools/k3btitlelabel.cpp new file mode 100644 index 0000000..9e1f18b --- /dev/null +++ b/libk3b/tools/k3btitlelabel.cpp @@ -0,0 +1,266 @@ +/* + * + * $Id: k3btitlelabel.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3btitlelabel.h" + +#include + +#include +#include +#include +#include +#include + + +class K3bTitleLabel::Private +{ +public: + Private() { + titleLength = subTitleLength = 0; + margin = 2; + alignment = Qt::AlignLeft; + cachedMinimumWidth = 0; + titleBaseLine = 0; + } + + QString title; + QString subTitle; + + QString displayTitle; + QString displaySubTitle; + + int alignment; + + int titleLength; + int subTitleLength; + int displayTitleLength; + int displaySubTitleLength; + int titleBaseLine; + int subTitleBaseLine; + int margin; + + int cachedMinimumWidth; +}; + + +class K3bTitleLabel::ToolTip : public QToolTip +{ +public: + ToolTip( K3bTitleLabel* label ) + : QToolTip( label ), + m_label(label) { + } + + void maybeTip( const QPoint &pos ) { + QRect r = m_label->contentsRect(); + + int neededWidth = m_label->d->displayTitleLength; + if( !m_label->d->displaySubTitle.isEmpty() ) + neededWidth += m_label->d->displaySubTitleLength + 5; + + int startPos = 0; + if( m_label->d->alignment & Qt::AlignHCenter ) + startPos = r.left() + ( r.width() - 2*m_label->d->margin - neededWidth ) / 2; + else if( m_label->d->alignment & Qt::AlignRight ) + startPos = r.right() - m_label->d->margin - neededWidth; + else + startPos = r.left() + m_label->d->margin; + + QRect titleTipRect( startPos, 0, m_label->d->displayTitleLength, m_label->height() ); + QRect subTitleTipRect( startPos + m_label->d->displayTitleLength, 0, m_label->d->displaySubTitleLength, m_label->height() ); + + if( titleTipRect.contains( pos ) && + m_label->d->displayTitle != m_label->d->title ) + tip( titleTipRect, m_label->d->title ); + else if( subTitleTipRect.contains( pos ) && + m_label->d->displaySubTitle != m_label->d->subTitle ) + tip( subTitleTipRect, m_label->d->subTitle ); + } + + K3bTitleLabel* m_label; +}; + + + +K3bTitleLabel::K3bTitleLabel( QWidget* parent, const char* name ) + : QFrame( parent, name ) +{ + d = new Private(); + m_toolTip = new ToolTip( this ); +} + + +K3bTitleLabel::~K3bTitleLabel() +{ + delete m_toolTip; + delete d; +} + + +void K3bTitleLabel::setTitle( const QString& title, const QString& subTitle ) +{ + d->title = title; + d->subTitle = subTitle; + updatePositioning(); + update(); +} + + +void K3bTitleLabel::setSubTitle( const QString& subTitle ) +{ + d->subTitle = subTitle; + updatePositioning(); + update(); +} + + +void K3bTitleLabel::setAlignment( int align ) +{ + d->alignment = align; + update(); +} + + +QSize K3bTitleLabel::sizeHint() const +{ + return QSize( d->titleLength + d->subTitleLength + 2*d->margin, d->titleBaseLine ); +} + +QSize K3bTitleLabel::minimumSizeHint() const +{ + return QSize( d->cachedMinimumWidth, d->titleBaseLine ); +} + +void K3bTitleLabel::resizeEvent( QResizeEvent* e ) +{ + QFrame::resizeEvent( e ); + updatePositioning(); + update(); +} + +void K3bTitleLabel::drawContents( QPainter* p ) +{ + p->save(); + + QRect r = contentsRect(); + p->eraseRect( r ); + + QFont f(font()); + f.setBold(true); + f.setPointSize( f.pointSize() + 2 ); + + p->setFont(f); + + int neededWidth = d->displayTitleLength; + if( !d->displaySubTitle.isEmpty() ) + neededWidth += d->displaySubTitleLength + 5; + + int startPos = 0; + if( d->alignment & Qt::AlignHCenter ) + startPos = r.left() + ( r.width() - 2*d->margin - neededWidth ) / 2; + else if( d->alignment & Qt::AlignRight ) + startPos = r.right() - d->margin - neededWidth; + else + startPos = r.left() + d->margin; + + // paint title + p->drawText( startPos, r.top() + d->titleBaseLine, d->displayTitle ); + + if( !d->subTitle.isEmpty() ) { + f.setBold(false); + f.setPointSize( f.pointSize() - 4 ); + p->setFont(f); + p->drawText( startPos + d->displayTitleLength + 5, r.top() + d->subTitleBaseLine, d->displaySubTitle ); + } + + p->restore(); +} + + +void K3bTitleLabel::setMargin( int m ) +{ + d->margin = m; + updatePositioning(); + update(); +} + + +void K3bTitleLabel::updatePositioning() +{ + QFont f(font()); + f.setBold(true); + f.setPointSize( f.pointSize() + 2 ); + QFontMetrics titleFm(f); + + f.setBold(false); + f.setPointSize( f.pointSize() - 4 ); + QFontMetrics subTitleFm(f); + + d->titleBaseLine = contentsRect().height()/2 + titleFm.height()/2 - titleFm.descent(); + d->titleLength = titleFm.width( d->title ); + + d->subTitleBaseLine = d->titleBaseLine - titleFm.underlinePos() + subTitleFm.underlinePos(); + + d->subTitleLength = ( d->subTitle.isEmpty() ? 0 : subTitleFm.width( d->subTitle ) ); + + // cut the text to window width + d->displayTitle = d->title; + d->displaySubTitle = d->subTitle; + int widthAvail = contentsRect().width() - 2*margin(); + + // 5 pix spacing between title and subtitle + if( !d->subTitle.isEmpty() ) + widthAvail -= 5; + + if( d->titleLength > widthAvail/2 ) { + if( d->subTitleLength <= widthAvail/2 ) + d->displayTitle = K3b::cutToWidth( titleFm, d->title, widthAvail - d->subTitleLength ); + else + d->displayTitle = K3b::cutToWidth( titleFm, d->title, widthAvail/2 ); + } + if( d->subTitleLength > widthAvail/2 ) { + if( d->titleLength <= widthAvail/2 ) + d->displaySubTitle = K3b::cutToWidth( subTitleFm, d->subTitle, widthAvail - d->titleLength ); + else + d->displaySubTitle = K3b::cutToWidth( subTitleFm, d->subTitle, widthAvail/2 ); + } + + d->displayTitleLength = titleFm.width( d->displayTitle ); + d->displaySubTitleLength = subTitleFm.width( d->displaySubTitle ); + + + // + // determine the minimum width for the minumum size hint + // + d->cachedMinimumWidth = 2*d->margin; + + QString cutTitle = d->title; + if( cutTitle.length() > 2 ) { + cutTitle.truncate( 2 ); + cutTitle += "..."; + } + QString cutSubTitle = d->subTitle; + if( cutSubTitle.length() > 2 ) { + cutSubTitle.truncate( 2 ); + cutSubTitle += "..."; + } + + d->cachedMinimumWidth += titleFm.width( cutTitle ) + subTitleFm.width( cutSubTitle ); + // 5 pix spacing between title and subtitle + if( !d->subTitle.isEmpty() ) + d->cachedMinimumWidth += 5; +} + +#include "k3btitlelabel.moc" diff --git a/libk3b/tools/k3btitlelabel.h b/libk3b/tools/k3btitlelabel.h new file mode 100644 index 0000000..ba1044d --- /dev/null +++ b/libk3b/tools/k3btitlelabel.h @@ -0,0 +1,68 @@ +/* + * + * $Id: k3btitlelabel.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef _K3B_TITLE_LABEL_H_ +#define _K3B_TITLE_LABEL_H_ + +#include +#include "k3b_export.h" +class QPainter; +class QResizeEvent; + + +class LIBK3B_EXPORT K3bTitleLabel : public QFrame +{ + Q_OBJECT + + public: + K3bTitleLabel( QWidget* parent = 0, const char* name = 0 ); + ~K3bTitleLabel(); + + QSize sizeHint() const; + QSize minimumSizeHint() const; + + public slots: + /** + * default: 2 + */ + void setMargin( int ); + + void setTitle( const QString& title, const QString& subTitle = QString::null ); + void setSubTitle( const QString& subTitle ); + + /** + * The title label only supports alignments left, hcenter, and right + * + * Default alignment is left. + */ + // FIXME: honor right-to-left languages + void setAlignment( int align ); + + protected: + void resizeEvent( QResizeEvent* ); + void drawContents( QPainter* p ); + + private: + void updatePositioning(); + + class ToolTip; + ToolTip* m_toolTip; + + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3btoolbox.cpp b/libk3b/tools/k3btoolbox.cpp new file mode 100644 index 0000000..b08dfc8 --- /dev/null +++ b/libk3b/tools/k3btoolbox.cpp @@ -0,0 +1,293 @@ +/* + * + * $Id$ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3btoolbox.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + * internal class. Do not use! + */ +class K3bToolBoxSeparator : public QWidget +{ + // Q_OBJECT + + public: + K3bToolBoxSeparator( K3bToolBox* parent ); + + QSize sizeHint() const; + + protected: + void paintEvent( QPaintEvent * ); +}; + + +K3bToolBoxSeparator::K3bToolBoxSeparator( K3bToolBox* parent ) + : QWidget( parent ) +{ + setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ) ); +} + + +QSize K3bToolBoxSeparator::sizeHint() const +{ + int extent = style().pixelMetric( QStyle::PM_DockWindowSeparatorExtent, + this ); + return QSize( extent, 0 ); +} + + +void K3bToolBoxSeparator::paintEvent( QPaintEvent* ) +{ + QPainter p( this ); + QStyle::SFlags flags = QStyle::Style_Default|QStyle::Style_Horizontal; + + style().drawPrimitive( QStyle::PE_DockWindowSeparator, &p, rect(), + colorGroup(), flags ); +} + + + +K3bToolBoxButton::K3bToolBoxButton( KAction* action, QWidget* parent ) + : QToolButton( parent ), + m_popupMenu(0) +{ + setSizePolicy( QSizePolicy(QSizePolicy::Fixed, sizePolicy().verData()) ); + setAutoRaise( true ); + + setIconSet( action->iconSet() ); + setTextLabel( action->text() ); + setEnabled( action->isEnabled() ); + + QWhatsThis::add( this, action->whatsThis() ); + if( action->toolTip().isEmpty() ) + QToolTip::add( this, action->text() ); + else + QToolTip::add( this, action->toolTip() ); + +// if( KToggleAction* ta = dynamic_cast( action ) ) { +// setToggleButton( true ); + +// // initial state +// if( ta->isChecked() ) +// toggle(); + +// connect( ta, SIGNAL(toggled(bool)), this, SLOT(toggle()) ); +// connect( this, SIGNAL(toggled(bool)), ta, SLOT(setChecked(bool)) ); +// } + +// else + if( KActionMenu* am = dynamic_cast( action ) ) { + m_popupMenu = am->popupMenu(); + connect( this, SIGNAL(pressed()), this, SLOT(slotPopupActivated()) ); + setPopup( m_popupMenu ); + } + + else { + connect( this, SIGNAL(clicked()), action, SLOT(activate()) ); + } + + connect( action, SIGNAL(enabled(bool)), this, SLOT(setEnabled(bool)) ); +} + + +K3bToolBoxButton::K3bToolBoxButton( const QString& text, const QString& icon, + const QString& tooltip, const QString& whatsthis, + QObject* receiver, const char* slot, + QWidget* parent ) + : QToolButton( parent ), + m_popupMenu(0) +{ + setSizePolicy( QSizePolicy(QSizePolicy::Fixed, sizePolicy().verData()) ); + setAutoRaise( true ); + + setTextLabel( text ); + + if( icon.isEmpty() ) + setUsesTextLabel( true ); + else + setIconSet( SmallIconSet( icon ) ); + + QWhatsThis::add( this, whatsthis ); + QToolTip::add( this, tooltip ); + + if( receiver && slot ) + connect( this, SIGNAL(clicked()), receiver, slot ); +} + + +void K3bToolBoxButton::slotPopupActivated() +{ + // force the toolbutton to open the popupmenu instantly + openPopup(); +} + + +void K3bToolBoxButton::resizeEvent( QResizeEvent* e ) +{ + QToolButton::resizeEvent( e ); + + // force icon-only buttons to be square + if( e->oldSize().height() != e->size().height() && + !usesTextLabel() ) + setFixedWidth( e->size().height() ); +} + + + + + + + +K3bToolBox::K3bToolBox( QWidget* parent, const char* name ) + : QFrame( parent, name ) +{ + setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed) ); + + m_mainLayout = new QGridLayout( this ); + m_mainLayout->setMargin( 1 ); + m_mainLayout->setSpacing( 0 ); +} + + +K3bToolBox::~K3bToolBox() +{ + clear(); +} + + +K3bToolBoxButton* K3bToolBox::addButton( KAction* action, bool forceText ) +{ + if( action ) { + K3bToolBoxButton* b = new K3bToolBoxButton( action, this ); + if( forceText ) { + b->setUsesTextLabel( true ); + b->setTextPosition( QToolButton::BesideIcon ); + } + addWidget( b ); + return b; + } + else + return 0; +} + + +K3bToolBoxButton* K3bToolBox::addButton( const QString& text, const QString& icon, + const QString& tooltip, const QString& whatsthis, + QObject* receiver, const char* slot, + bool forceText ) +{ + K3bToolBoxButton* b = new K3bToolBoxButton( text, icon, tooltip, whatsthis, receiver, slot, this ); + if( forceText ) { + b->setUsesTextLabel( true ); + b->setTextPosition( QToolButton::BesideIcon ); + } + addWidget( b ); + return b; +} + + +void K3bToolBox::addSpacing() +{ + int lastStretch = m_mainLayout->colStretch( m_mainLayout->numCols()-1 ); + m_mainLayout->setColStretch( m_mainLayout->numCols()-1, 0 ); + m_mainLayout->addColSpacing( m_mainLayout->numCols()-1, 8 ); + m_mainLayout->setColStretch( m_mainLayout->numCols(), lastStretch ); +} + + +void K3bToolBox::addSeparator() +{ + K3bToolBoxSeparator* s = new K3bToolBoxSeparator( this ); + addWidget( s ); +} + + +void K3bToolBox::addStretch() +{ + // add an empty widget + addWidget( new QWidget( this ) ); + m_mainLayout->setColStretch( m_mainLayout->numCols(), 1 ); +} + + +void K3bToolBox::addLabel( const QString& text ) +{ + QLabel* label = new QLabel( text, this ); + label->setSizePolicy( QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) ); + + addWidget( label ); +} + + +void K3bToolBox::addWidget( QWidget* w ) +{ + w->reparent( this, QPoint() ); + + m_mainLayout->setColStretch( m_mainLayout->numCols()-1, 0 ); + + m_mainLayout->addWidget( w, 0, m_mainLayout->numCols()-1 ); + + if( w->sizePolicy().horData() == QSizePolicy::Fixed || w->sizePolicy().horData() == QSizePolicy::Maximum ) + m_mainLayout->setColStretch( m_mainLayout->numCols(), 1 ); + else { + m_mainLayout->setColStretch( m_mainLayout->numCols()-1, 1 ); + m_mainLayout->setColStretch( m_mainLayout->numCols(), 0 ); + } +} + + +K3bToolBoxButton* K3bToolBox::addToggleButton( KToggleAction* action ) +{ + return addButton( action ); +} + + +void K3bToolBox::addWidgetAction( KWidgetAction* action ) +{ + addWidget( action->widget() ); + m_doNotDeleteWidgets.append( action->widget() ); +} + + +void K3bToolBox::clear() +{ + // we do not want to delete the widgets from the widgetactions becasue they + // might be used afterwards + for( QPtrListIterator it( m_doNotDeleteWidgets ); it.current(); ++it ) + it.current()->reparent( 0L, QPoint() ); + + for( QObjectListIterator it2( *children() ); it2.current(); ++it2 ) + if( it2.current()->isWidgetType() ) + delete it2.current(); +} + +#include "k3btoolbox.moc" diff --git a/libk3b/tools/k3btoolbox.h b/libk3b/tools/k3btoolbox.h new file mode 100644 index 0000000..828fca1 --- /dev/null +++ b/libk3b/tools/k3btoolbox.h @@ -0,0 +1,93 @@ +/* + * + * $Id$ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef K3B_TOOLBOX_H +#define K3B_TOOLBOX_H + +#include +#include +#include +#include +#include "k3b_export.h" + +class KAction; +class KToggleAction; +class KWidgetAction; +class QGridLayout; +class QPopupMenu; +class QResizeEvent; + + +/** + * internal class. Do not use! + */ +class LIBK3B_EXPORT K3bToolBoxButton : public QToolButton +{ + Q_OBJECT + + public: + K3bToolBoxButton( KAction*, QWidget* parent ); + K3bToolBoxButton( const QString& text, const QString& icon, + const QString& tooltip, const QString& whatsthis, + QObject* receiver, const char* slot, + QWidget* parent ); + + private slots: + void slotPopupActivated(); + + protected: + void resizeEvent( QResizeEvent* ); + + private: + QPopupMenu* m_popupMenu; +}; + + +class LIBK3B_EXPORT K3bToolBox : public QFrame +{ + Q_OBJECT + + public: + K3bToolBox( QWidget* parent = 0, const char* name = 0 ); + ~K3bToolBox(); + + K3bToolBoxButton* addButton( const QString& text, const QString& icon, + const QString& tooltip = QString::null, const QString& whatsthis = QString::null, + QObject* receiver = 0, const char* slot = 0, + bool forceTextLabel = false ); + K3bToolBoxButton* addButton( KAction*, bool forceTextLabel = false ); + K3bToolBoxButton* addToggleButton( KToggleAction* ); + void addWidgetAction( KWidgetAction* ); + + /** + * Be aware that the toolbox will take ownership of the widget + * and destroy it on destruction. Becasue of this it is not fitted + * for WidgetActions. + */ + void addWidget( QWidget* ); + void addLabel( const QString& ); + void addSpacing(); + void addSeparator(); + void addStretch(); + + void clear(); + + protected: + QGridLayout* m_mainLayout; + QPtrList m_doNotDeleteWidgets; +}; + + +#endif diff --git a/libk3b/tools/k3btoolbutton.cpp b/libk3b/tools/k3btoolbutton.cpp new file mode 100644 index 0000000..2e3e468 --- /dev/null +++ b/libk3b/tools/k3btoolbutton.cpp @@ -0,0 +1,109 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3btoolbutton.h" + +#include +#include +#include + +#include +#include + + +class K3bToolButton::Private +{ +public: + QPoint mousePressPos; + bool instantMenu; +}; + + +K3bToolButton::K3bToolButton( QWidget* parent ) + : QToolButton( parent ) +{ + d = new Private; + d->instantMenu = false; + installEventFilter(this); +} + + +K3bToolButton::~K3bToolButton() +{ + delete d; +} + + +void K3bToolButton::setInstantMenu( bool b ) +{ + d->instantMenu = b; +} + + +void K3bToolButton::drawButton( QPainter* p ) +{ + QToolButton::drawButton( p ); + + // + // code below comes from ktoolbarbutton.cpp from the kdelibs sources + // see the file for copyright information + // + if( QToolButton::popup() ) { + QStyle::SFlags arrowFlags = QStyle::Style_Default; + + if( isDown() ) + arrowFlags |= QStyle::Style_Down; + if( isEnabled() ) + arrowFlags |= QStyle::Style_Enabled; + + style().drawPrimitive(QStyle::PE_ArrowDown, p, + QRect(width()-7, height()-7, 7, 7), colorGroup(), + arrowFlags, QStyleOption() ); + } +} + + +bool K3bToolButton::eventFilter( QObject* o, QEvent* ev ) +{ + if( dynamic_cast(o) == this ) { + + // Popup the menu when the left mousebutton is pressed and the mouse + // is moved by a small distance. + if( QToolButton::popup() ) { + if( ev->type() == QEvent::MouseButtonPress ) { + QMouseEvent* mev = static_cast(ev); + + if( d->instantMenu ) { + setDown(true); + openPopup(); + return true; + } + else { + d->mousePressPos = mev->pos(); + } + } + else if( ev->type() == QEvent::MouseMove ) { + QMouseEvent* mev = static_cast(ev); + if( !d->instantMenu && + ( mev->pos() - d->mousePressPos).manhattanLength() > KGlobalSettings::dndEventDelay() ) { + openPopup(); + return true; + } + } + } + } + + return QToolButton::eventFilter( o, ev ); +} diff --git a/libk3b/tools/k3btoolbutton.h b/libk3b/tools/k3btoolbutton.h new file mode 100644 index 0000000..fe96e4c --- /dev/null +++ b/libk3b/tools/k3btoolbutton.h @@ -0,0 +1,50 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_TOOL_BUTTON_H_ +#define _K3B_TOOL_BUTTON_H_ + +#include "k3b_export.h" + +#include + +class QPainter; +class QEvent; + + +/** + * the K3bToolButton is an enhanced QToolButton which adds two functionalities: + *

  • A delayed popup menu is shown immiadetely once the mouse is dragged downwards + * much like the KToolBarButton + *
  • If a popup menu is set a little arrow indicates this. + */ +class LIBK3B_EXPORT K3bToolButton : public QToolButton +{ + public: + K3bToolButton( QWidget* parent = 0 ); + ~K3bToolButton(); + + void setInstantMenu( bool ); + + protected: + virtual void drawButton( QPainter* ); + virtual bool eventFilter( QObject*, QEvent* ); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/libk3b/tools/k3bvalidators.cpp b/libk3b/tools/k3bvalidators.cpp new file mode 100644 index 0000000..9252fdd --- /dev/null +++ b/libk3b/tools/k3bvalidators.cpp @@ -0,0 +1,154 @@ +/* + * + * $Id: k3bvalidators.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bvalidators.h" + +#include + + +K3bCharValidator::K3bCharValidator( QObject* parent, const char* name ) + : QValidator( parent, name ), + m_replaceChar( '_' ) +{ +} + + +QValidator::State K3bCharValidator::validate( QString& s, int& pos ) const +{ + Q_UNUSED(pos); + + for( unsigned int i = 0; i < s.length(); ++i ) { + State r = validateChar( s[i] ); + if( r != Acceptable ) + return r; + } + + return Acceptable; +} + + +void K3bCharValidator::fixup( QString& s ) const +{ + for( unsigned int i = 0; i < s.length(); ++i ) { + if( validateChar( s[i] ) != Acceptable ) + s[i] = m_replaceChar; + } +} + + +K3bLatin1Validator::K3bLatin1Validator( QObject* parent, const char* name ) + : K3bCharValidator( parent, name ) +{ +} + + +QValidator::State K3bLatin1Validator::validateChar( const QChar& c ) const +{ + if( !c.latin1() ) + return Invalid; + else + return Acceptable; +} + + +K3bAsciiValidator::K3bAsciiValidator( QObject* parent, const char* name ) + : K3bLatin1Validator( parent, name ) +{ +} + + +QValidator::State K3bAsciiValidator::validateChar( const QChar& c ) const +{ + if( K3bLatin1Validator::validateChar( c ) == Invalid ) + return Invalid; + else if( !isascii( c.latin1() ) ) + return Invalid; + else + return Acceptable; +} + + + +K3bValidator::K3bValidator( QObject* parent, const char* name ) + : QRegExpValidator( parent, name ), + m_replaceChar('_') +{ +} + + +K3bValidator::K3bValidator( const QRegExp& rx, QObject* parent, const char* name ) + : QRegExpValidator( rx, parent, name ), + m_replaceChar('_') +{ +} + + +void K3bValidator::fixup( QString& input ) const +{ + for( unsigned int i = 0; i < input.length(); ++i ) + if( !regExp().exactMatch( input.mid(i, 1) ) ) + input[i] = m_replaceChar; +} + + +QString K3bValidators::fixup( const QString& input, const QRegExp& rx, const QChar& replaceChar ) +{ + QString s; + for( unsigned int i = 0; i < input.length(); ++i ) + if( rx.exactMatch( input.mid(i, 1) ) ) + s += input[i]; + else + s += replaceChar; + return s; +} + + +K3bValidator* K3bValidators::isrcValidator( QObject* parent, const char* name ) +{ + return new K3bValidator( QRegExp("^[A-Z\\d]{2,2}-[A-Z\\d]{3,3}-\\d{2,2}-\\d{5,5}$"), parent, name ); +} + + +K3bValidator* K3bValidators::iso9660Validator( bool allowEmpty, QObject* parent, const char* name ) +{ + if( allowEmpty ) + return new K3bValidator( QRegExp( "[^/]*" ), parent, name ); + else + return new K3bValidator( QRegExp( "[^/]+" ), parent, name ); +} + + +K3bValidator* K3bValidators::iso646Validator( int type, bool AllowLowerCase, QObject* parent, const char* name ) +{ + QRegExp rx; + switch ( type ) { + case Iso646_d: + if ( AllowLowerCase ) + rx = QRegExp( "[a-zA-Z0-9_]*" ); + else + rx = QRegExp( "[A-Z0-9_]*" ); + break; + case Iso646_a: + default: + if ( AllowLowerCase ) + rx = QRegExp( "[a-zA-Z0-9!\"\\s%&'\\(\\)\\*\\+,\\-\\./:;<=>\\?_]*" ); + else + rx = QRegExp( "[A-Z0-9!\"\\s%&'\\(\\)\\*\\+,\\-\\./:;<=>\\?_]*" ); + break; + } + + return new K3bValidator( rx, parent, name ); +} diff --git a/libk3b/tools/k3bvalidators.h b/libk3b/tools/k3bvalidators.h new file mode 100644 index 0000000..89c6397 --- /dev/null +++ b/libk3b/tools/k3bvalidators.h @@ -0,0 +1,131 @@ +/* + * + * $Id: k3bvalidators.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003-2007 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VALIDATORS_H_ +#define _K3B_VALIDATORS_H_ + +#include +#include "k3b_export.h" + + +/** + * Simple validator that validates a string char by char + */ +class LIBK3B_EXPORT K3bCharValidator : public QValidator +{ + public: + K3bCharValidator( QObject* parent = 0, const char* name = 0 ); + + virtual State validateChar( const QChar& ) const = 0; + + virtual State validate( QString& s, int& pos ) const; + + /** + * Replaces all invalid chars with the repplace char + */ + virtual void fixup( QString& ) const; + + /** + * Default to '_' + */ + void setReplaceChar( const QChar& c ) { m_replaceChar = c; } + + private: + QChar m_replaceChar; +}; + + +class LIBK3B_EXPORT K3bLatin1Validator : public K3bCharValidator +{ + public: + K3bLatin1Validator( QObject* parent = 0, const char* name = 0 ); + + virtual State validateChar( const QChar& ) const; +}; + + +class LIBK3B_EXPORT K3bAsciiValidator : public K3bLatin1Validator +{ + public: + K3bAsciiValidator( QObject* parent = 0, const char* name = 0 ); + + virtual State validateChar( const QChar& ) const; +}; + + +/** + * The K3bValidator extends QRegExpValidator with a fixup method + * that just replaces all characters that are not allowed with the + * replace character. It only makes sense for QRegExps that simply + * allow or forbid some characters. + */ +class LIBK3B_EXPORT K3bValidator : public QRegExpValidator +{ + public: + K3bValidator( QObject* parent, const char * name = 0 ); + K3bValidator( const QRegExp& rx, QObject* parent, const char* name = 0 ); + + void setReplaceChar( const QChar& s ) { m_replaceChar = s; } + const QChar& replaceChar() const { return m_replaceChar; } + + virtual void fixup( QString& ) const; + + private: + QChar m_replaceChar; +}; + + +namespace K3bValidators +{ + /** + * just replaces all characters that are not allowed with the + * replace character. It only makes sense for QRegExps that simply + * allow or forbid some characters. + */ + LIBK3B_EXPORT QString fixup( const QString&, const QRegExp&, const QChar& replaceChar = '_' ); + + /** + * Validates an ISRC code of the form "CCOOOYYSSSSS" where: + *
      + *
    • C: country code (upper case letters or digits)
    • + *
    • O: owner code (upper case letters or digits)
    • + *
    • Y: year (digits)
    • + *
    • S: serial number (digits)
    • + *
    + */ + LIBK3B_EXPORT K3bValidator* isrcValidator( QObject* parent = 0, const char* name = 0 ); + + /** + * This needs to be replaced by something better in the future... + * Even the name sucks! + */ + LIBK3B_EXPORT K3bValidator* iso9660Validator( bool allowEmpty = true, QObject* parent = 0, const char* name = 0 ); + + /** + * (1) d-characters are: A-Z, 0-9, _ (see ISO-9660:1988, Annex A, Table 15) + * (2) a-characters are: A-Z, 0-9, _, space, !, ", %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ? + * (see ISO-9660:1988, Annex A, Table 14) + */ + enum Iso646Type { + Iso646_a, + Iso646_d + }; + + LIBK3B_EXPORT K3bValidator* iso646Validator( int type = Iso646_a, + bool AllowLowerCase = false, + QObject* parent = 0, const char* name = 0 ); +} + +#endif diff --git a/libk3b/tools/k3bwavefilewriter.cpp b/libk3b/tools/k3bwavefilewriter.cpp new file mode 100644 index 0000000..36267c2 --- /dev/null +++ b/libk3b/tools/k3bwavefilewriter.cpp @@ -0,0 +1,186 @@ +/* + * + * $Id: k3bwavefilewriter.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bwavefilewriter.h" +#include + +K3bWaveFileWriter::K3bWaveFileWriter() + : m_outputStream( &m_outputFile ) +{ +} + + +K3bWaveFileWriter::~K3bWaveFileWriter() +{ + close(); +} + + +bool K3bWaveFileWriter::open( const QString& filename ) +{ + close(); + + m_outputFile.setName( filename ); + + if( m_outputFile.open( IO_ReadWrite ) ) { + m_filename = filename; + + writeEmptyHeader(); + + return true; + } + else { + return false; + } +} + + +void K3bWaveFileWriter::close() +{ + if( isOpen() ) { + if( m_outputFile.at() > 0 ) { + padTo2352(); + + // update wave header + updateHeader(); + + m_outputFile.close(); + } + else { + m_outputFile.close(); + m_outputFile.remove(); + } + } + + m_filename = QString::null; +} + + +bool K3bWaveFileWriter::isOpen() +{ + return m_outputFile.isOpen(); +} + + +const QString& K3bWaveFileWriter::filename() const +{ + return m_filename; +} + + +void K3bWaveFileWriter::write( const char* data, int len, Endianess e ) +{ + if( isOpen() ) { + if( e == LittleEndian ) { + m_outputStream.writeRawBytes( data, len ); + } + else { + if( len % 2 > 0 ) { + kdDebug() << "(K3bWaveFileWriter) data length (" + << len << ") is not a multiple of 2! Cannot swap bytes." << endl; + return; + } + + // we need to swap the bytes + char* buffer = new char[len]; + for( int i = 0; i < len-1; i+=2 ) { + buffer[i] = data[i+1]; + buffer[i+1] = data[i]; + } + m_outputStream.writeRawBytes( buffer, len ); + + delete [] buffer; + } + } +} + + +void K3bWaveFileWriter::writeEmptyHeader() +{ + static const char riffHeader[] = + { + 0x52, 0x49, 0x46, 0x46, // 0 "RIFF" + 0x00, 0x00, 0x00, 0x00, // 4 wavSize + 0x57, 0x41, 0x56, 0x45, // 8 "WAVE" + 0x66, 0x6d, 0x74, 0x20, // 12 "fmt " + 0x10, 0x00, 0x00, 0x00, // 16 + 0x01, 0x00, 0x02, 0x00, // 20 + 0x44, 0xac, 0x00, 0x00, // 24 + 0x10, 0xb1, 0x02, 0x00, // 28 + 0x04, 0x00, 0x10, 0x00, // 32 + 0x64, 0x61, 0x74, 0x61, // 36 "data" + 0x00, 0x00, 0x00, 0x00 // 40 byteCount + }; + + m_outputStream.writeRawBytes( riffHeader, 44 ); +} + + +void K3bWaveFileWriter::updateHeader() +{ + if( isOpen() ) { + + m_outputFile.flush(); + + Q_INT32 dataSize( m_outputFile.at() - 44 ); + Q_INT32 wavSize(dataSize + 44 - 8); + char c[4]; + + // jump to the wavSize position in the header + if( m_outputFile.at( 4 ) ) { + c[0] = (wavSize >> 0 ) & 0xff; + c[1] = (wavSize >> 8 ) & 0xff; + c[2] = (wavSize >> 16) & 0xff; + c[3] = (wavSize >> 24) & 0xff; + m_outputStream.writeRawBytes( c, 4 ); + } + else + kdDebug() << "(K3bWaveFileWriter) unable to seek in file: " << m_outputFile.name() << endl; + + if( m_outputFile.at( 40 ) ) { + c[0] = (dataSize >> 0 ) & 0xff; + c[1] = (dataSize >> 8 ) & 0xff; + c[2] = (dataSize >> 16) & 0xff; + c[3] = (dataSize >> 24) & 0xff; + m_outputStream.writeRawBytes( c, 4 ); + } + else + kdDebug() << "(K3bWaveFileWriter) unable to seek in file: " << m_outputFile.name() << endl; + + // jump back to the end + m_outputFile.at( m_outputFile.size() ); + } +} + + +void K3bWaveFileWriter::padTo2352() +{ + int bytesToPad = ( m_outputFile.at() - 44 ) % 2352; + if( bytesToPad > 0 ) { + kdDebug() << "(K3bWaveFileWriter) padding wave file with " << bytesToPad << " bytes." << endl; + + char* c = new char[bytesToPad]; + memset( c, 0, bytesToPad ); + m_outputStream.writeRawBytes( c, bytesToPad ); + delete [] c; + } +} + + +int K3bWaveFileWriter::fd() const +{ + return m_outputFile.handle(); +} diff --git a/libk3b/tools/k3bwavefilewriter.h b/libk3b/tools/k3bwavefilewriter.h new file mode 100644 index 0000000..e5394a5 --- /dev/null +++ b/libk3b/tools/k3bwavefilewriter.h @@ -0,0 +1,78 @@ +/* + * + * $Id: k3bwavefilewriter.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef K3BWAVEFILEWRITER_H +#define K3BWAVEFILEWRITER_H + +#include +#include +#include +#include "k3b_export.h" +/** + * @author Sebastian Trueg + * Creates wave files from 16bit stereo little or big endian + * sound samples + */ +class LIBK3B_EXPORT K3bWaveFileWriter +{ + public: + + enum Endianess { BigEndian, LittleEndian }; + + K3bWaveFileWriter(); + ~K3bWaveFileWriter(); + + /** + * open a new wave file. + * closes any opened file. + */ + bool open( const QString& filename ); + + bool isOpen(); + const QString& filename() const; + + /** + * closes the file. + * Length of the wave file will be written into the header. + * If no data has been written to the file except the header + * it will be removed. + */ + void close(); + + /** + * write 16bit samples to the file. + * @param e the endianess of the data + * (it will be swapped to little endian byte order if necessary) + */ + void write( const char* data, int len, Endianess e = BigEndian ); + + /** + * returnes a filedescriptor with the already opened file + * or -1 if isOpen() is false + */ + int fd() const; + + private: + void writeEmptyHeader(); + void updateHeader(); + void padTo2352(); + + QFile m_outputFile; + QDataStream m_outputStream; + QString m_filename; +}; + +#endif diff --git a/libk3b/tools/kcutlabel.cpp b/libk3b/tools/kcutlabel.cpp new file mode 100644 index 0000000..accbe17 --- /dev/null +++ b/libk3b/tools/kcutlabel.cpp @@ -0,0 +1,115 @@ +/* + * + * $Id: kcutlabel.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "kcutlabel.h" + +#include + +#include +#include +#include + + +KCutLabel::KCutLabel( const QString &text , QWidget *parent, const char *name ) + : QLabel ( parent, name ), + m_minChars(1) { + QSizePolicy myLabelSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + setSizePolicy(myLabelSizePolicy); + m_fullText = text; + cutTextToLabel(); +} + +KCutLabel::KCutLabel( QWidget *parent, const char *name ) + : QLabel ( parent, name ), + m_minChars(1) { + QSizePolicy myLabelSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + setSizePolicy(myLabelSizePolicy); +} + +QSize KCutLabel::minimumSizeHint() const +{ + QSize sh = QLabel::minimumSizeHint(); + if( m_minChars == 0 ) + sh.setWidth(-1); + else if( m_minChars < (int)m_fullText.length() ) + sh.setWidth( QMIN( fontMetrics().width( m_fullText.left(m_minChars) + "..." ), + fontMetrics().width( m_fullText ) ) ); + + return sh; +} + + +void KCutLabel::setMinimumVisibleText( int i ) +{ + m_minChars = i; + cutTextToLabel(); +} + + +void KCutLabel::resizeEvent( QResizeEvent * ) +{ + cutTextToLabel(); +} + +void KCutLabel::setText( const QString &text ) +{ + m_fullText = text; + cutTextToLabel(); +} + + +const QString& KCutLabel::fullText() const +{ + return m_fullText; +} + + +void KCutLabel::cutTextToLabel() +{ + QToolTip::remove( this ); + QToolTip::hide(); + + if( m_fullText.contains( "\n" ) ) { + QString newText; + QStringList lines = QStringList::split( "\n", m_fullText ); + for( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) { + QString squeezedText = K3b::cutToWidth( fontMetrics(), + *it, + QMAX( size().width(), + QMIN( fontMetrics().width( m_fullText.left(m_minChars) + "..." ), + fontMetrics().width( m_fullText ) ) ) ); + newText += squeezedText; + newText += "\n"; + if( squeezedText != *it ) + QToolTip::add( this, m_fullText ); + } + newText.truncate( newText.length() - 1 ); // get rid of the last newline + + QLabel::setText( newText ); + } + else { + QString squeezedText = K3b::cutToWidth( fontMetrics(), + m_fullText, + QMAX( size().width(), + QMIN( fontMetrics().width( m_fullText.left(m_minChars) + "..." ), + fontMetrics().width( m_fullText ) ) ) ); + QLabel::setText( squeezedText ); + if( squeezedText != m_fullText ) + QToolTip::add( this, m_fullText ); + } +} + +#include "kcutlabel.moc" diff --git a/libk3b/tools/kcutlabel.h b/libk3b/tools/kcutlabel.h new file mode 100644 index 0000000..6cf459c --- /dev/null +++ b/libk3b/tools/kcutlabel.h @@ -0,0 +1,68 @@ +/* + * + * $Id: kcutlabel.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef KCUTLABEL_H +#define KCUTLABEL_H + +#include +#include "k3b_export.h" + + +/* + * @ref QLabel + */ +class LIBK3B_EXPORT KCutLabel : public QLabel +{ + Q_OBJECT + + public: + /** + * Default constructor. + */ + KCutLabel( QWidget *parent = 0, const char *name = 0); + KCutLabel( const QString &text, QWidget *parent = 0, const char *name = 0 ); + + virtual QSize minimumSizeHint() const; + + /** + * \return the full text while text() returns the cut text + */ + const QString& fullText() const; + + public slots: + void setText( const QString & ); + + /** + * \param i the number of characters that have to be visible. Default is 1. + */ + void setMinimumVisibleText( int i ); + + protected: + /** + * used when widget is resized + */ + void resizeEvent( QResizeEvent * ); + /** + * does the dirty work + */ + void cutTextToLabel(); + + private: + QString m_fullText; + int m_minChars; +}; + +#endif // KCUTLABEL_H diff --git a/libk3b/tools/libisofs/COPYING b/libk3b/tools/libisofs/COPYING new file mode 100644 index 0000000..9fe1a71 --- /dev/null +++ b/libk3b/tools/libisofs/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Steet, Fifth Floor, Cambridge, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/libk3b/tools/libisofs/ChangeLog b/libk3b/tools/libisofs/ChangeLog new file mode 100644 index 0000000..78d7e66 --- /dev/null +++ b/libk3b/tools/libisofs/ChangeLog @@ -0,0 +1,9 @@ +K3b Changes +- renamed the st_xxx time fileds in rr_entry to rr_st_xxx to make it compile + +0.1 -> 0.2 + +- Critical directory parsing bug fixed +- Call backs only if some sanity checks on the directory entry succeeds + (length checks to avoid buffer overrun if received corrupt data) +- Preliminary El Torito boot specification support (No multiple boot entries yet) diff --git a/libk3b/tools/libisofs/Makefile.am b/libk3b/tools/libisofs/Makefile.am new file mode 100644 index 0000000..cd5594c --- /dev/null +++ b/libk3b/tools/libisofs/Makefile.am @@ -0,0 +1,5 @@ +AM_CPPFLAGS= $(all_includes) + +noinst_LTLIBRARIES = libisofs.la + +libisofs_la_SOURCES = isofs.cpp diff --git a/libk3b/tools/libisofs/README b/libk3b/tools/libisofs/README new file mode 100644 index 0000000..3657861 --- /dev/null +++ b/libk3b/tools/libisofs/README @@ -0,0 +1,24 @@ +This is the 0.2 release of libisofs. For changes, see the ChangeLog. + +Libisofs implements the reading of the famous ISO-9660 (ECMA-167) file system, +found on CD-ROM media. It also supports the Rock Ridge Interchange Protocol and +Microsoft Joliet extensions. It allows user-mode programs to query the +filesystem volume descriptors and traverse through the directory structure. +Preliminary support for El-Torito boot CDs are added in version 0.2. + +To use it in your project, I recommend to copy bswap.h, isofs.h, iso_fs.h, +el_torito.h rock.h and isofs.c to your sources, and include isofs.h in the +appropriate places. + +Currently only the directory tables are parsed, the path tables are not. +(The path tables contain redundant information.) + +Also a sample program can be compiled with the supplied Makefile. Simply +execute 'make', it should create the executable file isofs. + +On big-endian systems, you need to define WORDS_BIGENDIAN (either in the +compiler command-line, or if you defined HAVE_CONFIG_H, in config.h) + + +György Szombathelyi +http://libcdrom.sourceforge.net/libisofs.html diff --git a/libk3b/tools/libisofs/bswap.h b/libk3b/tools/libisofs/bswap.h new file mode 100644 index 0000000..96bd588 --- /dev/null +++ b/libk3b/tools/libisofs/bswap.h @@ -0,0 +1,94 @@ +/* From the mplayer project (www.mplayerhq.hu) */ + +#ifndef __BSWAP_H__ +#define __BSWAP_H__ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_BYTESWAP_H +#include +#else + +#ifdef ARCH_X86 +inline static unsigned short ByteSwap16(unsigned short x) +{ + __asm("xchgb %b0,%h0" : + "=q" (x) : + "0" (x)); + return x; +} +#define bswap_16(x) ByteSwap16(x) + +inline static unsigned int ByteSwap32(unsigned int x) +{ +#if defined(__CPU__) && (__CPU__ > 386) + __asm("bswap %0": + "=r" (x) : +#else + __asm("xchgb %b0,%h0\n" + " rorl $16,%0\n" + " xchgb %b0,%h0": + "=q" (x) : +#endif + "0" (x)); + return x; +} +#define bswap_32(x) ByteSwap32(x) + +inline static unsigned long long int ByteSwap64(unsigned long long int x) +{ + register union { __extension__ unsigned long long int __ll; + unsigned int __l[2]; } __x; + asm("xchgl %0,%1": + "=r"(__x.__l[0]),"=r"(__x.__l[1]): + "0"(bswap_32((unsigned long)x)),"1"(bswap_32((unsigned long)(x>>32)))); + return __x.__ll; +} +#define bswap_64(x) ByteSwap64(x) + +#else + +#define bswap_16(x) (((x) & 0x00ff) << 8 | ((x) & 0xff00) >> 8) + + +/* code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc. */ +#define bswap_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#define bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned int __l[2]; } __w, __r; \ + __w.__ll = (x); \ + __r.__l[0] = bswap_32 (__w.__l[1]); \ + __r.__l[1] = bswap_32 (__w.__l[0]); \ + __r.__ll; })) +#endif /* !ARCH_X86 */ + +#endif /* !HAVE_BYTESWAP_H */ + +/* + be2me ... BigEndian to MachineEndian + le2me ... LittleEndian to MachineEndian +*/ + +#ifdef WORDS_BIGENDIAN +#define be2me_16(x) (x) +#define be2me_32(x) (x) +#define be2me_64(x) (x) +#define le2me_16(x) bswap_16(x) +#define le2me_32(x) bswap_32(x) +#define le2me_64(x) bswap_64(x) +#else +#define be2me_16(x) bswap_16(x) +#define be2me_32(x) bswap_32(x) +#define be2me_64(x) bswap_64(x) +#define le2me_16(x) (x) +#define le2me_32(x) (x) +#define le2me_64(x) (x) +#endif + +#endif diff --git a/libk3b/tools/libisofs/el_torito.h b/libk3b/tools/libisofs/el_torito.h new file mode 100644 index 0000000..cba83f7 --- /dev/null +++ b/libk3b/tools/libisofs/el_torito.h @@ -0,0 +1,63 @@ +#ifndef ELTORITO_H +#define ELTORITO_H 1 + +#include "iso_fs.h" + +#define EL_TORITO_ID "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0" + +struct el_torito_boot_descriptor { + char type [ISODCL ( 1, 1)]; /* 711 */ + char id [ISODCL ( 2, 6)]; + char version [ISODCL ( 7, 7)]; /* 711 */ + char system_id [ISODCL ( 8, 39)]; /* achars */ + char unused [ISODCL ( 40, 71)]; + char boot_catalog [ISODCL ( 72, 75)]; /* 731 */ +}; + +struct validation_entry { + char type [ISODCL ( 1, 1)]; /* 1 */ + char platform [ISODCL ( 2, 2)]; + char unused [ISODCL ( 3, 4)]; + char id [ISODCL ( 5, 28)]; + char cheksum [ISODCL ( 29, 30)]; + char key [ISODCL ( 31, 31)]; /* 0x55 */ + char key2 [ISODCL ( 32, 32)]; /* 0xaa */ +}; + +struct default_entry { + char bootid [ISODCL ( 1, 1)]; + char media [ISODCL ( 2, 2)]; + char loadseg [ISODCL ( 3, 4)]; + char systype [ISODCL ( 5, 5)]; + char unused [ISODCL ( 6, 6)]; + char seccount [ISODCL ( 7, 8)]; + char start [ISODCL ( 9, 12)]; + char unused2 [ISODCL ( 13, 32)]; +}; + +struct section_header { + char headerid [ISODCL ( 1, 1)]; + char platform [ISODCL ( 2, 2)]; + char entries [ISODCL ( 3, 4)]; + char id [ISODCL ( 5, 32)]; +}; + +struct section_entry { + char bootid [ISODCL ( 1, 1)]; + char media [ISODCL ( 2, 2)]; + char loadseg [ISODCL ( 3, 4)]; + char systype [ISODCL ( 5, 5)]; + char unused [ISODCL ( 6, 6)]; + char seccount [ISODCL ( 7, 8)]; + char start [ISODCL ( 9, 12)]; + char selcrit [ISODCL ( 13, 13)]; + char vendor_selcrit [ISODCL ( 14, 32)]; +}; + +struct section_entry_ext { + char extid [ISODCL ( 1, 1)]; + char extrec [ISODCL ( 2, 2)]; + char vendor_selcrit [ISODCL ( 3, 32)]; +}; + +#endif diff --git a/libk3b/tools/libisofs/iso_fs.h b/libk3b/tools/libisofs/iso_fs.h new file mode 100644 index 0000000..43353b0 --- /dev/null +++ b/libk3b/tools/libisofs/iso_fs.h @@ -0,0 +1,219 @@ +/* From the linux kernel */ + +#ifndef _ISO_FS_H +#define _ISO_FS_H 1 + +#include "bswap.h" + +/* + * The isofs filesystem constants/structures + */ + +/* This part borrowed from the bsd386 isofs */ +#define ISODCL(from, to) (to - from + 1) + +struct iso_volume_descriptor { + char type[ISODCL(1,1)]; /* 711 */ + char id[ISODCL(2,6)]; + char version[ISODCL(7,7)]; + char data[ISODCL(8,2048)]; +}; + +/* volume descriptor types */ +#define ISO_VD_BOOT 0 +#define ISO_VD_PRIMARY 1 +#define ISO_VD_SUPPLEMENTARY 2 +#define ISO_VD_END 255 + +#define ISO_STANDARD_ID "CD001" + +struct iso_primary_descriptor { + char type [ISODCL ( 1, 1)]; /* 711 */ + char id [ISODCL ( 2, 6)]; + char version [ISODCL ( 7, 7)]; /* 711 */ + char unused1 [ISODCL ( 8, 8)]; + char system_id [ISODCL ( 9, 40)]; /* achars */ + char volume_id [ISODCL ( 41, 72)]; /* dchars */ + char unused2 [ISODCL ( 73, 80)]; + char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + char unused3 [ISODCL ( 89, 120)]; + char volume_set_size [ISODCL (121, 124)]; /* 723 */ + char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + char logical_block_size [ISODCL (129, 132)]; /* 723 */ + char path_table_size [ISODCL (133, 140)]; /* 733 */ + char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + char volume_set_id [ISODCL (191, 318)]; /* dchars */ + char publisher_id [ISODCL (319, 446)]; /* achars */ + char preparer_id [ISODCL (447, 574)]; /* achars */ + char application_id [ISODCL (575, 702)]; /* achars */ + char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + char file_structure_version [ISODCL (882, 882)]; /* 711 */ + char unused4 [ISODCL (883, 883)]; + char application_data [ISODCL (884, 1395)]; + char unused5 [ISODCL (1396, 2048)]; +}; + +/* Almost the same as the primary descriptor but two fields are specified */ +struct iso_supplementary_descriptor { + char type [ISODCL ( 1, 1)]; /* 711 */ + char id [ISODCL ( 2, 6)]; + char version [ISODCL ( 7, 7)]; /* 711 */ + char flags [ISODCL ( 8, 8)]; /* 853 */ + char system_id [ISODCL ( 9, 40)]; /* achars */ + char volume_id [ISODCL ( 41, 72)]; /* dchars */ + char unused2 [ISODCL ( 73, 80)]; + char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + char escape [ISODCL ( 89, 120)]; /* 856 */ + char volume_set_size [ISODCL (121, 124)]; /* 723 */ + char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + char logical_block_size [ISODCL (129, 132)]; /* 723 */ + char path_table_size [ISODCL (133, 140)]; /* 733 */ + char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + char volume_set_id [ISODCL (191, 318)]; /* dchars */ + char publisher_id [ISODCL (319, 446)]; /* achars */ + char preparer_id [ISODCL (447, 574)]; /* achars */ + char application_id [ISODCL (575, 702)]; /* achars */ + char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + char file_structure_version [ISODCL (882, 882)]; /* 711 */ + char unused4 [ISODCL (883, 883)]; + char application_data [ISODCL (884, 1395)]; + char unused5 [ISODCL (1396, 2048)]; +}; + +#define HS_STANDARD_ID "CDROM" + +struct hs_volume_descriptor { + char foo [ISODCL ( 1, 8)]; /* 733 */ + char type [ISODCL ( 9, 9)]; /* 711 */ + char id [ISODCL ( 10, 14)]; + char version [ISODCL ( 15, 15)]; /* 711 */ + char data[ISODCL(16,2048)]; +}; + + +struct hs_primary_descriptor { + char foo [ISODCL ( 1, 8)]; /* 733 */ + char type [ISODCL ( 9, 9)]; /* 711 */ + char id [ISODCL ( 10, 14)]; + char version [ISODCL ( 15, 15)]; /* 711 */ + char unused1 [ISODCL ( 16, 16)]; /* 711 */ + char system_id [ISODCL ( 17, 48)]; /* achars */ + char volume_id [ISODCL ( 49, 80)]; /* dchars */ + char unused2 [ISODCL ( 81, 88)]; /* 733 */ + char volume_space_size [ISODCL ( 89, 96)]; /* 733 */ + char unused3 [ISODCL ( 97, 128)]; /* 733 */ + char volume_set_size [ISODCL (129, 132)]; /* 723 */ + char volume_sequence_number [ISODCL (133, 136)]; /* 723 */ + char logical_block_size [ISODCL (137, 140)]; /* 723 */ + char path_table_size [ISODCL (141, 148)]; /* 733 */ + char type_l_path_table [ISODCL (149, 152)]; /* 731 */ + char unused4 [ISODCL (153, 180)]; /* 733 */ + char root_directory_record [ISODCL (181, 214)]; /* 9.1 */ +}; + +/* We use this to help us look up the parent inode numbers. */ + +struct iso_path_table{ + char name_len[1]; /* 711 */ + char ext_attr_length[1]; /* 711 */ + char extent[4]; /* 731 */ + char parent[2]; /* 721 */ + char name[1]; +}; + +/* high sierra is identical to iso, except that the date is only 6 bytes, and + there is an extra reserved byte after the flags */ + +struct iso_directory_record { + char length [ISODCL (1, 1)]; /* 711 */ + char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + char extent [ISODCL (3, 10)]; /* 733 */ + char size [ISODCL (11, 18)]; /* 733 */ + char date [ISODCL (19, 25)]; /* 7 by 711 */ + char flags [ISODCL (26, 26)]; + char file_unit_size [ISODCL (27, 27)]; /* 711 */ + char interleave [ISODCL (28, 28)]; /* 711 */ + char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + char name_len [ISODCL (33, 33)]; /* 711 */ + char name [1]; +}; + +/* 8 bit numbers */ +__inline unsigned char isonum_711(char *p); +__inline char isonum_712(char *p); + +/* 16 bit numbers */ +__inline unsigned short isonum_721(char *p); +__inline unsigned short isonum_722(char *p); +__inline unsigned short isonum_723(char *p); + +/* 32 bit numbers */ +__inline unsigned int isonum_731(char *p); +__inline unsigned int isonum_732(char *p); +__inline unsigned int isonum_733(char *p); + + +/* 8 bit numbers */ +__inline unsigned char isonum_711(char *p) +{ + return *(unsigned char *)p; +} +__inline char isonum_712(char *p) +{ + return *p; +} + +/* 16 bit numbers */ +__inline unsigned short isonum_721(char *p) +{ + return le2me_16(*(unsigned short *)p); +} +__inline unsigned short isonum_722(char *p) +{ + return be2me_16(*(unsigned short *)p); +} +__inline unsigned short isonum_723(char *p) +{ + /* Ignore bigendian datum due to broken mastering programs */ + return le2me_16(*(unsigned short *)p); +} + +/* 32 bit numbers */ +__inline unsigned int isonum_731(char *p) +{ + return le2me_32(*(unsigned int *)p); +} + +__inline unsigned int isonum_732(char *p) +{ + return be2me_32(*(unsigned int *)p); +} + +__inline unsigned int isonum_733(char *p) +{ + /* Ignore bigendian datum due to broken mastering programs */ + return le2me_32(*(unsigned int *)p); +} + +#endif /*_ISOFS_H*/ + diff --git a/libk3b/tools/libisofs/isofs.cpp b/libk3b/tools/libisofs/isofs.cpp new file mode 100644 index 0000000..e5c871b --- /dev/null +++ b/libk3b/tools/libisofs/isofs.cpp @@ -0,0 +1,878 @@ +/*************************************************************************** + isofs.c - libisofs implementation + ------------------- + begin : Oct 25 2002 + copyright : (C) 2002 by Szombathelyi György + email : gyurco@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include +#include + +#include "isofs.h" +#include "rock.h" + + + +/* internal function from the linux kernel (isofs fs) */ +static time_t getisotime(int year,int month,int day,int hour, + int minute,int second,int tz) { + + int days, i; + time_t crtime; + + year-=1970; + + if (year < 0) { + crtime = 0; + } else { + int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + + days = year * 365; + if (year > 2) + days += (year+1) / 4; + for (i = 1; i < month; i++) + days += monlen[i-1]; + if (((year+2) % 4) == 0 && month > 2) + days++; + days += day - 1; + crtime = ((((days * 24) + hour) * 60 + minute) * 60) + + second; + + /* sign extend */ + if (tz & 0x80) + tz |= (-1 << 8); + + /* + * The timezone offset is unreliable on some disks, + * so we make a sanity check. In no case is it ever + * more than 13 hours from GMT, which is 52*15min. + * The time is always stored in localtime with the + * timezone offset being what get added to GMT to + * get to localtime. Thus we need to subtract the offset + * to get to true GMT, which is what we store the time + * as internally. On the local system, the user may set + * their timezone any way they wish, of course, so GMT + * gets converted back to localtime on the receiving + * system. + * + * NOTE: mkisofs in versions prior to mkisofs-1.10 had + * the sign wrong on the timezone offset. This has now + * been corrected there too, but if you are getting screwy + * results this may be the explanation. If enough people + * complain, a user configuration option could be added + * to add the timezone offset in with the wrong sign + * for 'compatibility' with older discs, but I cannot see how + * it will matter that much. + * + * Thanks to kuhlmav@elec.canterbury.ac.nz (Volker Kuhlmann) + * for pointing out the sign error. + */ + if (-52 <= tz && tz <= 52) + crtime -= tz * 15 * 60; + } + return crtime; + +} + +/** + * Returns the Unix from the ISO9660 9.1.5 time format + */ +time_t isodate_915(char * p, int hs) { + + return getisotime(1900+p[0],p[1],p[2],p[3],p[4],p[5],hs==0 ? p[6] : 0); +} + +/** + * Returns the Unix from the ISO9660 8.4.26.1 time format + * BUG: hundredth of seconds are ignored, because Unix time_t has one second + * resolution (I think it's no problem at all) + */ +time_t isodate_84261(char * p, int hs) { + int year,month,day,hour,minute,second; + year=(p[0]-'0')*1000 + (p[1]-'0')*100 + (p[2]-'0')*10 + p[3]-'0'; + month=(p[4]-'0')*10 + (p[5]-'0'); + day=(p[6]-'0')*10 + (p[7]-'0'); + hour=(p[8]-'0')*10 + (p[9]-'0'); + minute=(p[10]-'0')*10 + (p[11]-'0'); + second=(p[12]-'0')*10 + (p[13]-'0'); + return getisotime(year,month,day,hour,minute,second,hs==0 ? p[16] : 0); +} + +void FreeBootTable(boot_head *boot) { + boot_entry *be,*next; + + be=boot->defentry; + while (be) { + next=be->next; + free(be); + be=next; + } + boot->defentry=NULL; +} + +int BootImageSize(readfunc* read,int media,sector_t start,int len,void* udata) { + int ret; + + switch(media & 0xf) { + case 0: + ret=len; /* No emulation */ + break; + case 1: + ret=80*2*15; /* 1.2 MB */ + break; + case 2: + ret=80*2*18; /* 1.44 MB */ + break; + case 3: + ret=80*2*36; /* 2.88 MB */ + break; + case 4: + /* FIXME!!! */ + ret=len; /* Hard Disk */ + break; + default: + ret=len; + } + return ret; +} + +static boot_entry *CreateBootEntry(char *be) { + boot_entry *entry; + + entry = (boot_entry*) malloc(sizeof(boot_entry)); + if (!entry) return NULL; + memset(entry, 0, sizeof(boot_entry)); + memcpy(entry->data,be,0x20); + return entry; +} + +int ReadBootTable(readfunc *read,sector_t sector, boot_head *head, void *udata) { + + char buf[2048], *c, *be; + int i,end=0; + unsigned short sum; + boot_entry *defcur=NULL,*deflast=NULL; + register struct validation_entry *ventry=NULL; + register struct default_entry *dentry=NULL; + register struct section_header *sheader=NULL; + register struct section_entry *sentry=NULL; + register struct section_entry_ext *extsentry=NULL; + + head->sections=NULL; + head->defentry=NULL; + while (1) { + be = (char*) &buf; + if ( read(be, sector, 1, udata) != 1 ) goto err; + + /* first entry needs to be a validation entry */ + if (!ventry) { + ventry=(struct validation_entry *) be; + if ( isonum_711(ventry->type) !=1 ) goto err; + sum=0; + c = (char*) ventry; + for (i=0;i<16;i++) { sum += isonum_721(c); c+=2; } + if (sum) goto err; + memcpy(&head->ventry,be,0x20); + be += 0x20; + } + + while (!end && (be < (buf+1))) { + switch (isonum_711(be)) { + case 0x88: + defcur=CreateBootEntry(be); + if (!defcur) goto err; + if (deflast) + deflast->next=defcur; + else + head->defentry=defcur; + defcur->prev=deflast; + deflast=defcur; + break; + case 0x90: + case 0x91: + break; + default: + end=1; + break; + } + be += 0x20; + } + if (end) break; + + sector ++; + } + + return 0; + +err: + FreeBootTable(head); + return -1; +} + + +/** + * Creates the linked list of the volume descriptors + */ +iso_vol_desc *ReadISO9660(readfunc *read,sector_t sector,void *udata) { + + int i; + struct iso_volume_descriptor buf; + iso_vol_desc *first=NULL,*current=NULL,*prev=NULL; + + for (i=0;i<100;i++) { + if (read( (char*) &buf, sector+i+16, 1, udata) != 1 ) { + FreeISO9660(first); + return NULL; + } + if (!memcmp(ISO_STANDARD_ID,&buf.id,5)) { + switch ( isonum_711(&buf.type[0]) ) { + + case ISO_VD_BOOT: + case ISO_VD_PRIMARY: + case ISO_VD_SUPPLEMENTARY: + current=(iso_vol_desc*) malloc(sizeof(iso_vol_desc)); + if (!current) { + FreeISO9660(first); + return NULL; + } + current->prev=prev; + current->next=NULL; + if (prev) prev->next=current; + memcpy(&(current->data),&buf,2048); + if (!first) first=current; + prev=current; + break; + + case ISO_VD_END: + return first; + break; + } + } else if (!memcmp(HS_STANDARD_ID,(struct hs_volume_descriptor*) &buf,5)) { + /* High Sierra format not supported (yet) */ + } + } + + return first; +} + +/** + * Frees the linked list of volume descriptors + */ +void FreeISO9660(iso_vol_desc *data) { + + iso_vol_desc *current; + + + while (data) { + current=data; + data=current->next; + free(current); + } +} + +/** + * Frees the strings in 'rrentry' + */ +void FreeRR(rr_entry *rrentry) { + if (rrentry->name) { + free(rrentry->name); + rrentry->name=NULL; + } + if (rrentry->sl) { + free(rrentry->sl); + rrentry->name=NULL; + } +} + +static int str_nappend(char **d,char *s,int n) { + int i=0; + char *c; + +/* i=strnlen(s,n)+1; */ + while (iname_len); + if (!(isonum_711(idr->name_len) & 1)) suspoffs++; + susplen=isonum_711(idr->length)-suspoffs; + r= & (((char*) idr)[suspoffs]); + rr = (struct rock_ridge*) r; + + memset(rrentry,0,sizeof(rr_entry)); + rrentry->len = sizeof(rr_entry); + + while (susplen > 0) { + if (isonum_711(&rr->len) > susplen || rr->len == 0) break; + if (rr->signature[0]=='N' && rr->signature[1]=='M') { + if (!(rr->u.NM.flags & 0x26) && rr->len>5 && !rrentry->name) { + + if (str_nappend(&rrentry->name,rr->u.NM.name,isonum_711(&rr->len)-5)) { + FreeRR(rrentry); return -ENOMEM; + } + ret++; + } + } else if (rr->signature[0]=='P' && rr->signature[1]=='X' && + (isonum_711(&rr->len)==44 || isonum_711(&rr->len)==36)) { + rrentry->mode=isonum_733(rr->u.PX.mode); + rrentry->nlink=isonum_733(rr->u.PX.n_links); + rrentry->uid=isonum_733(rr->u.PX.uid); + rrentry->gid=isonum_733(rr->u.PX.gid); + if (isonum_711(&rr->len)==44) rrentry->serno=isonum_733(rr->u.PX.serno); + ret++; + } else if (rr->signature[0]=='P' && rr->signature[1]=='N' && + isonum_711(&rr->len)==20) { + rrentry->dev_major=isonum_733(rr->u.PN.dev_high); + rrentry->dev_minor=isonum_733(rr->u.PN.dev_low); + ret++; + } else if (rr->signature[0]=='P' && rr->signature[1]=='L' && + isonum_711(&rr->len)==12) { + rrentry->pl=isonum_733(rr->u.PL.location); + ret++; + } else if (rr->signature[0]=='C' && rr->signature[1]=='L' && + isonum_711(&rr->len)==12) { + rrentry->cl=isonum_733(rr->u.CL.location); + ret++; + } else if (rr->signature[0]=='R' && rr->signature[1]=='E' && + isonum_711(&rr->len)==4) { + rrentry->re=1; + ret++; + } else if (rr->signature[0]=='S' && rr->signature[1]=='L' && + isonum_711(&rr->len)>7) { + i = isonum_711(&rr->len)-5; + c = (char*) rr; + c += 5; + while (i>0) { + switch(c[0] & ~1) { + case 0x2: + if (str_append(&rrentry->sl,".")) { + FreeRR(rrentry); return -ENOMEM; + } + break; + case 0x4: + if (str_append(&rrentry->sl,"..")) { + FreeRR(rrentry); return -ENOMEM; + } + break; + } + if ( (c[0] & 0x08) == 0x08 || (c[1] && rrentry->sl && + strlen(rrentry->sl)>1) ) { + if (str_append(&rrentry->sl,"/")) { + FreeRR(rrentry); return -ENOMEM; + } + } + + if ((unsigned char)c[1]>0) { + if (str_nappend(&rrentry->sl,c+2,(unsigned char)c[1])) { + FreeRR(rrentry); return -ENOMEM; + } + } + i -= ((unsigned char)c[1] + 2); + c += ((unsigned char)c[1] + 2); + } + ret++; + } else if (rr->signature[0]=='T' && rr->signature[1]=='F' && + isonum_711(&rr->len)>5) { + + i = isonum_711(&rr->len)-5; + f = rr->u.TF.flags; + c = (char*) rr; + c += 5; + + while (i >= rrtlen(f)) { + if (f & 1) { + rrentry->t_creat=rrctime(f,c); + f &= ~1; + } else if (f & 2) { + rrentry->rr_st_mtime=rrctime(f,c); + f &= ~2; + } else if (f & 4) { + rrentry->rr_st_atime=rrctime(f,c); + f &= ~4; + } else if (f & 8) { + rrentry->rr_st_ctime=rrctime(f,c); + f &= ~8; + } else if (f & 16) { + rrentry->t_backup=rrctime(f,c); + f &= ~16; + } else if (f & 32) { + rrentry->t_expire=rrctime(f,c); + f &= ~32; + } else if (f & 64) { + rrentry->t_effect=rrctime(f,c); + f &= ~64; + } + + i -= rrtlen(f); + c += rrtlen(f); + } + ret++; + + } else if (rr->signature[0]=='Z' && rr->signature[1]=='F' && + isonum_711(&rr->len)==16) { + /* Linux-specific extension: transparent decompression */ + rrentry->z_algo[0]=rr->u.ZF.algorithm[0]; + rrentry->z_algo[1]=rr->u.ZF.algorithm[1]; + rrentry->z_params[0]=rr->u.ZF.parms[0]; + rrentry->z_params[1]=rr->u.ZF.parms[1]; + rrentry->z_size=isonum_733(rr->u.ZF.real_size); + ret++; + } else { +/* printf("SUSP sign: %c%c\n",rr->signature[0],rr->signature[1]); */ + } + + susplen -= isonum_711(&rr->len); + r += isonum_711(&rr->len); + rr = (struct rock_ridge*) r; + } + + return ret; +} + +/** + * Iterates over the directory entries. The directory is in 'buf', + * the size of the directory is 'size'. 'callback' is called for each + * directory entry with the parameter 'udata'. + */ +int ProcessDir(readfunc *read,int extent,int size,dircallback *callback,void *udata) { + + int pos=0,ret=0,siz; + char *buf; + struct iso_directory_record *idr; + + if (size & 2047) { + siz=((size>>11)+1)<<11; + } else { + siz=size; + } + + buf=(char*) malloc(siz); + if (!buf) return -ENOMEM; + if (read(buf,extent,siz>>11,udata)!=siz>>11) { + free(buf); + return -EIO; + } + + while (size>0) { + idr=(struct iso_directory_record*) &buf[pos]; + if (isonum_711(idr->length)==0) { + size-=(2048 - (pos & 0x7ff)); + if (size<=2) break; + pos+=0x800; + pos&=0xfffff800; + idr=(struct iso_directory_record*) &buf[pos]; + } + pos+=isonum_711(idr->length); + pos+=isonum_711(idr->ext_attr_length); + size-=isonum_711(idr->length); + size-=isonum_711(idr->ext_attr_length); + if (size<0) break; + + if (isonum_711(idr->length) +<33 || + isonum_711(idr->length)<33+isonum_711(idr->name_len)) { + /* Invalid directory entry */ + continue; + } + if ((ret=callback(idr,udata))) break; + } + + free(buf); + return ret; +} + +/** + * returns the joliet level from the volume descriptor + */ +int JolietLevel(struct iso_volume_descriptor *ivd) { + int ret=0; + register struct iso_supplementary_descriptor *isd; + + isd = (struct iso_supplementary_descriptor *) ivd; + + if (isonum_711(ivd->type)==ISO_VD_SUPPLEMENTARY) { + if (isd->escape[0]==0x25 && + isd->escape[1]==0x2f) { + + switch (isd->escape[2]) { + case 0x40: + ret=1; + break; + case 0x43: + ret=2; + break; + case 0x45: + ret=3; + break; + } + } + } + return ret; +} + +/********************************************************************/ +#if 0 + +#include +#include +#include +#include +#include +#include +#include + +int level=0,joliet=0,dirs,files; +iconv_t iconv_d; +int fd; + +int readf(char *buf, int start, int len,void *udata) { + int ret; + + if ((ret=lseek(fd, start << 11, SEEK_SET))<0) return ret; + ret=read(fd, buf, len << 11); + if (ret<0) return ret; + return (ret >> 11); +} + +void dumpchars(char *c,int len) { + while (len>0) { + printf("%c",*c); + len--; + c++; + } +} + +void sp(int num) { + int i; + for (i=0;iname_len)==1) { + switch (dir->name[0]) { + case 0: + printf("."); + break; + case 1: + printf(".."); + break; + default: + printf("%c",dir->name[0]); + break; + } + } + dumpchardesc(dir->name,isonum_711(dir->name_len)); + printf(" size=%d",isonum_733(dir->size)); + printf(" extent=%d ",isonum_733(dir->extent)); + dumpflags(isonum_711(dir->flags)); + dumpiso915time((char*) &(dir->date),0); +} + +void dumprrentry(rr_entry *rr) { + printf(" NM=[%s] uid=%d gid=%d nlink=%d mode=%o ", + rr->name,rr->uid,rr->gid,rr->nlink,rr->mode); + if (S_ISCHR(rr->mode) || S_ISBLK(rr->mode)) + printf("major=%d minor=%d ",rr->dev_major,rr->dev_minor); + if (rr->mode & S_IFLNK && rr->sl) printf("slink=%s ",rr->sl); +/* + printf("\n"); + if (rr->t_creat) printf("t_creat: %s",ctime(&rr->t_creat)); + if (rr->rr_st_mtime) printf("rr_st_mtime: %s",ctime(&rr->rr_st_mtime)); + if (rr->rr_st_atime) printf("rr_st_atime: %s",ctime(&rr->rr_st_atime)); + if (rr->rr_st_ctime) printf("rr_st_ctime: %s",ctime(&rr->rr_st_ctime)); + if (rr->t_backup) printf("t_backup: %s",ctime(&rr->t_backup)); + if (rr->t_expire) printf("t_expire: %s",ctime(&rr->t_expire)); + if (rr->t_effect) printf("t_effect: %s",ctime(&rr->t_effect)); +*/ +} + +void dumpsusp(char *c, int len) { + dumpchars(c,len); +} + +void dumpboot(struct el_torito_boot_descriptor *ebd) { + printf("version: %d\n",isonum_711(ebd->version)); + printf("system id: ");dumpchars(ebd->system_id,ISODCL(8,39));printf("\n"); + printf("boot catalog start: %d\n",isonum_731(ebd->boot_catalog)); +} + +void dumpdefentry(struct default_entry *de) { + printf("Default entry: \n"); + printf(" bootid=%x\n",isonum_711(de->bootid)); + printf(" media emulation=%d (",isonum_711(de->media)); + switch(isonum_711(de->media) & 0xf) { + case 0: + printf("No emulation"); + break; + case 1: + printf("1.2 Mb floppy"); + break; + case 2: + printf("1.44 Mb floppy"); + break; + case 3: + printf("2.88 Mb floppy"); + break; + case 4: + printf("Hard Disk"); + break; + default: + printf("Unknown/Invalid"); + break; + } + printf(")\n"); + printf(" loadseg=%d\n",isonum_721(de->loadseg)); + printf(" systype=%d\n",isonum_711(de->systype)); + printf(" start lba=%d count=%d\n",isonum_731(de->start), + isonum_721(de->seccount)); +} + +void dumpbootcat(boot_head *bh) { + boot_entry *be; + + printf("System id: ");dumpchars(bh->ventry.id,ISODCL(28,5));printf("\n"); + be=bh->defentry; + while (be) { + dumpdefentry(be->data); + be=be->next; + } +} + +void dumpdesc(struct iso_primary_descriptor *ipd) { + + printf("system id: ");dumpchardesc(ipd->system_id,ISODCL(9,40));printf("\n"); + printf("volume id: ");dumpchardesc(ipd->volume_id,ISODCL(41,72));printf("\n"); + printf("volume space size: %d\n",isonum_733(ipd->volume_space_size)); + printf("volume set size: %d\n",isonum_723(ipd->volume_set_size)); + printf("volume seq num: %d\n",isonum_723(ipd->volume_set_size)); + printf("logical block size: %d\n",isonum_723(ipd->logical_block_size)); + printf("path table size: %d\n",isonum_733(ipd->path_table_size)); + printf("location of type_l path table: %d\n",isonum_731(ipd->type_l_path_table)); + printf("location of optional type_l path table: %d\n",isonum_731(ipd->opt_type_l_path_table)); + printf("location of type_m path table: %d\n",isonum_732(ipd->type_m_path_table)); + printf("location of optional type_m path table: %d\n",isonum_732(ipd->opt_type_m_path_table)); +/* + printf("Root dir record:\n");dumpdirrec((struct iso_directory_record*) &ipd->root_directory_record); +*/ + printf("Volume set id: ");dumpchardesc(ipd->volume_set_id,ISODCL(191,318));printf("\n"); + printf("Publisher id: ");dumpchardesc(ipd->publisher_id,ISODCL(319,446));printf("\n"); + printf("Preparer id: ");dumpchardesc(ipd->preparer_id,ISODCL(447,574));printf("\n"); + printf("Application id: ");dumpchardesc(ipd->application_id,ISODCL(575,702));printf("\n"); + printf("Copyright id: ");dumpchardesc(ipd->copyright_file_id,ISODCL(703,739));printf("\n"); + printf("Abstract file id: ");dumpchardesc(ipd->abstract_file_id,ISODCL(740,776));printf("\n"); + printf("Bibliographic file id: ");dumpchardesc(ipd->bibliographic_file_id,ISODCL(777,813));printf("\n"); + printf("Volume creation date: ");dumpiso84261time(ipd->creation_date,0);printf("\n"); + printf("Volume modification date: ");dumpiso84261time(ipd->modification_date,0);printf("\n"); + printf("Volume expiration date: ");dumpiso84261time(ipd->expiration_date,0);printf("\n"); + printf("Volume effective date: ");dumpiso84261time(ipd->effective_date,0);printf("\n"); + printf("File structure version: %d\n",isonum_711(ipd->file_structure_version)); +} + +int mycallb(struct iso_directory_record *idr,void *udata) { + rr_entry rrentry; + + sp(level);dumpdirrec(idr); + if (level==0) printf(" (Root directory) "); + printf("\n"); + + if (ParseRR(idr,&rrentry)>0) { + sp(level);printf(" ");dumprrentry(&rrentry);printf("\n"); + } + FreeRR(&rrentry); + if ( !(idr->flags[0] & 2) ) files++; + if ( (idr->flags[0] & 2) && (level==0 || isonum_711(idr->name_len)>1) ) { + level++; + dirs++; + ProcessDir(&readf,isonum_733(idr->extent),isonum_733(idr->size),&mycallb,udata); + level--; + } + return 0; +} + +/************************************************/ + +int main(int argc, char *argv[]) { + + int i=1,sector=0; + iso_vol_desc *desc; + boot_head boot; + + if (argc<2) { + fprintf(stderr,"\nUsage: %s iso-file-name or device [starting sector]\n\n",argv[0]); + return 0; + } + if (argc>=3) { + sector=atoi(argv[2]); + printf("Using starting sector number %d\n",sector); + } + fd=open(argv[1],O_RDONLY); + if (fd<0) { + fprintf(stderr,"open error\n"); + return -1; + } + iconv_d=iconv_open("ISO8859-2","UTF16BE"); + if (iconv_d==0) { + fprintf(stderr,"iconv open error\n"); + return -1; + } + + desc=ReadISO9660(&readf,sector,NULL); + if (!desc) { + printf("No volume descriptors\n"); + return -1; + } + while (desc) { + + printf("\n\n--------------- Volume descriptor (%d.) type %d: ---------------\n\n", + i,isonum_711(desc->data.type)); + switch (isonum_711(desc->data.type)) { + case ISO_VD_BOOT: { + + struct el_torito_boot_descriptor* bootdesc; + bootdesc=&(desc->data); + dumpboot(bootdesc); + if ( !memcmp(EL_TORITO_ID,bootdesc->system_id,ISODCL(8,39)) ) { + + if (ReadBootTable(&readf,isonum_731(bootdesc->boot_catalog),&boot,NULL)) { + printf("Boot Catalog Error\n"); + } else { + dumpbootcat(&boot); + FreeBootTable(&boot); + } + } + } + break; + + case ISO_VD_PRIMARY: + case ISO_VD_SUPPLEMENTARY: + joliet=0; + joliet = JolietLevel(&desc->data); + printf("Joliet level: %d\n",joliet); + dumpdesc((struct iso_primary_descriptor*) &desc->data); + printf("\n\n--------------- Directory structure: -------------------\n\n"); + dirs=0;files=0; + mycallb( &( ((struct iso_primary_descriptor*) &desc->data)->root_directory_record), NULL ); + printf("\nnumber of directories: %d\n",dirs); + printf("\nnumber of files: %d\n",files); + break; + + } + desc=desc->next; + i++; + } + iconv_close(iconv_d); + close(fd); + FreeISO9660(desc); + return 0; +} + +#endif diff --git a/libk3b/tools/libisofs/isofs.h b/libk3b/tools/libisofs/isofs.h new file mode 100644 index 0000000..f284903 --- /dev/null +++ b/libk3b/tools/libisofs/isofs.h @@ -0,0 +1,151 @@ +/*************************************************************************** + isofs.h - include this file to use libisofs + ------------------- + begin : Oct 25 2002 + copyright : (C) 2002 by Szombathelyi György + email : gyurco@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef ISOFS_H +#define ISOFS_H + +#include + +#include "iso_fs.h" +#include "el_torito.h" + +typedef long sector_t; + +typedef struct _rr_entry { + int len; /* length of structure */ + char *name; /* Name from 'NM' */ + char *sl; /* symbolic link data */ + time_t t_creat; + time_t rr_st_mtime; + time_t rr_st_atime; + time_t rr_st_ctime; + time_t t_backup; + time_t t_expire; + time_t t_effect; + int mode; /* POSIX file modes */ + int nlink; + int uid; + int gid; + int serno; + int dev_major; + int dev_minor; + int pl; /* parent location */ + int cl; /* child location */ + int re; /* relocated */ + char z_algo[2]; /* zizofs algorithm */ + char z_params[2]; /* zizofs parameters */ + int z_size; /* zizofs real_size */ +} rr_entry; + +typedef struct _iso_vol_desc { + struct _iso_vol_desc *next; + struct _iso_vol_desc *prev; + struct iso_volume_descriptor data; +} iso_vol_desc; + +typedef struct _boot_entry { + struct _boot_entry *next; + struct _boot_entry *prev; + struct _boot_entry *parent; + struct _boot_entry *child; + char data[32]; +} boot_entry; + +typedef struct _boot_head { + struct validation_entry ventry; + struct _boot_entry *defentry; + struct _boot_entry *sections; +} boot_head; + +/** + * this callback function needs to read 'len' sectors from 'start' into 'buf' + */ +typedef int readfunc(char *buf,sector_t start, int len,void *); + +/** + * ProcessDir uses this callback + */ +typedef int dircallback(struct iso_directory_record *,void *); + +/** + * Returns the Unix from the ISO9660 9.1.5 (7 bytes) time format + * This function is from the linux kernel. + * Set 'hs' to non-zero if it's a HighSierra volume + */ +time_t isodate_915(char * p, int hs); + +/** + * Returns the Unix time from the ISO9660 8.4.26.1 (17 bytes) time format + * BUG: hundredth of seconds are ignored, because time_t has one second + * resolution (I think it's no problem at all) + * Set 'hs' to non-zero if it's a HighSierra volume + */ +time_t isodate_84261(char * p, int hs); + +/** + * Creates the linked list of the volume descriptors + * 'sector' is the starting sector number of where the filesystem start + * (starting sector of a session on a CD-ROM) + * If the function fails, returns NULL + * Don't forget to call FreeISO9660 after using the volume descriptor list! + */ +iso_vol_desc *ReadISO9660(readfunc *read,sector_t sector,void *udata); + +/** + * Frees the linked list of volume descriptors. + */ +void FreeISO9660(iso_vol_desc *data); + +/** + * Iterates over the directory entries. The directory is in 'buf', + * the size of the directory is 'size'. 'callback' is called for each + * directory entry with the parameter 'udata'. + */ +int ProcessDir(readfunc *read,int extent,int size,dircallback *callback,void *udata); + +/** + * Parses the System Use area and fills rr_entry with values + */ +int ParseRR(struct iso_directory_record *idr, rr_entry *rrentry); + +/** + * Frees the strings in 'rrentry' + */ +void FreeRR(rr_entry *rrentry); + +/** + * returns the joliet level from the volume descriptor + */ +int JolietLevel(struct iso_volume_descriptor *ivd); + +/** + * Returns the size of the boot image (in 512 byte sectors) + */ +int BootImageSize(readfunc *read,int media,sector_t start,int len,void *udata); + +/** + * Frees the boot catalog entries in 'boot'. If you ever called ReadBootTable, + * then don't forget to call FreeBootTable! + */ +void FreeBootTable(boot_head *boot); + +/** + * Reads the boot catalog into 'head'. Don't forget to call FreeBootTable! + */ +int ReadBootTable(readfunc *read,sector_t sector, boot_head *head, void *udata); + +#endif diff --git a/libk3b/tools/libisofs/rock.h b/libk3b/tools/libisofs/rock.h new file mode 100644 index 0000000..e859192 --- /dev/null +++ b/libk3b/tools/libisofs/rock.h @@ -0,0 +1,127 @@ +/* this header is from the linux kernel */ + +#ifndef ROCK_H +#define ROCK_H 1 + +/* These structs are used by the system-use-sharing protocol, in which the + Rock Ridge extensions are embedded. It is quite possible that other + extensions are present on the disk, and this is fine as long as they + all use SUSP */ + +struct SU_SP{ + unsigned char magic[2]; + unsigned char skip; +}; + +struct SU_CE{ + char extent[8]; + char offset[8]; + char size[8]; +}; + +struct SU_ER{ + unsigned char len_id; + unsigned char len_des; + unsigned char len_src; + unsigned char ext_ver; + char data[1]; +}; + +struct RR_RR{ + char flags[1]; +}; + +struct RR_PX{ + char mode[8]; + char n_links[8]; + char uid[8]; + char gid[8]; + char serno[8]; +}; + +struct RR_PN{ + char dev_high[8]; + char dev_low[8]; +}; + + +struct SL_component{ + unsigned char flags; + unsigned char len; + char text[1]; +}; + +struct RR_SL{ + unsigned char flags; + struct SL_component link; +}; + +struct RR_NM{ + unsigned char flags; + char name[1]; +}; + +struct RR_CL{ + char location[8]; +}; + +struct RR_PL{ + char location[8]; +}; + +struct stamp{ + char time[7]; +}; + +struct RR_TF{ + char flags; + struct stamp times[1]; /* Variable number of these beasts */ +}; + +/* Linux-specific extension for transparent decompression */ +struct RR_ZF{ + char algorithm[2]; + char parms[2]; + char real_size[8]; +}; + +/* These are the bits and their meanings for flags in the TF structure. */ +#define TF_CREATE 1 +#define TF_MODIFY 2 +#define TF_ACCESS 4 +#define TF_ATTRIBUTES 8 +#define TF_BACKUP 16 +#define TF_EXPIRATION 32 +#define TF_EFFECTIVE 64 +#define TF_LONG_FORM 128 + +struct rock_ridge{ + char signature[2]; + char len; /* 711 */ + char version; /* 711 */ + union{ + struct SU_SP SP; + struct SU_CE CE; + struct SU_ER ER; + struct RR_RR RR; + struct RR_PX PX; + struct RR_PN PN; + struct RR_SL SL; + struct RR_NM NM; + struct RR_CL CL; + struct RR_PL PL; + struct RR_TF TF; + struct RR_ZF ZF; + } u; +}; + +#define RR_PX 1 /* POSIX attributes */ +#define RR_PN 2 /* POSIX devices */ +#define RR_SL 4 /* Symbolic link */ +#define RR_NM 8 /* Alternate Name */ +#define RR_CL 16 /* Child link */ +#define RR_PL 32 /* Parent link */ +#define RR_RE 64 /* Relocation directory */ +#define RR_TF 128 /* Timestamps */ + +#endif /* ROCK_H */ diff --git a/libk3b/videodvd/Makefile.am b/libk3b/videodvd/Makefile.am new file mode 100644 index 0000000..0225117 --- /dev/null +++ b/libk3b/videodvd/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = -I$(srcdir) \ + -I$(srcdir)/../core \ + -I$(srcdir)/../../libk3bdevice \ + -I$(srcdir)/../tools \ + -I$(srcdir)/../plugin \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libvideodvd.la +libvideodvd_la_LIBADD = -ldvdread + +libvideodvd_la_SOURCES = k3bvideodvd.cpp k3bvideodvdtime.cpp \ + k3bvideodvdvideostream.cpp + +include_HEADERS = k3bvideodvd.h k3bvideodvdtitle.h \ + k3bvideodvdaudiostream.h k3bvideodvdsubpicturestream.h \ + k3bvideodvdvideostream.h k3bvideodvdtime.h \ + k3bvideodvdptt.h diff --git a/libk3b/videodvd/configure.in.bot b/libk3b/videodvd/configure.in.bot new file mode 100644 index 0000000..7ed988b --- /dev/null +++ b/libk3b/videodvd/configure.in.bot @@ -0,0 +1,11 @@ +echo "" + +echo "K3b - Include libdvdread (Video DVD ripping) support:" +if test "$have_libdvdread" = "yes"; then + echo "K3b - yes" +else + echo "K3b - no" + if test "$ac_cv_use_libdvdread" = "yes"; then + echo "K3b - You are missing the libdvdread library." + fi +fi diff --git a/libk3b/videodvd/configure.in.in b/libk3b/videodvd/configure.in.in new file mode 100644 index 0000000..f5ec969 --- /dev/null +++ b/libk3b/videodvd/configure.in.in @@ -0,0 +1,28 @@ +AC_ARG_WITH( + libdvdread, + AS_HELP_STRING( + [--without-libdvdread], + [build K3b without libdvdread (Video DVD ripping) support (default=no)]), + [ac_cv_use_libdvdread=$withval], + [ac_cv_use_libdvdread=yes] +) + +have_libdvdread=no +if test "$ac_cv_use_libdvdread" = "yes"; then + KDE_CHECK_HEADERS(dvdread/dvd_reader.h, + [ + AC_CHECK_LIB(dvdread, + DVDOpen, + [ + AC_DEFINE(HAVE_LIBDVDREAD,1,[Defined if you have libdvdread headers and libs installed.]) + have_libdvdread=yes + ] + ) + ]) +fi +AM_CONDITIONAL(include_videodvdrip, [test x$have_libdvdread = xyes]) + +#if test "$have_libdvdread" = "no"; then +# AC_MSG_ERROR([Could not find libdvdread. Please install.]) +# DO_NOT_COMPILE="$DO_NOT_COMPILE k3b" +#fi diff --git a/libk3b/videodvd/k3bvideodvd.cpp b/libk3b/videodvd/k3bvideodvd.cpp new file mode 100644 index 0000000..8692c04 --- /dev/null +++ b/libk3b/videodvd/k3bvideodvd.cpp @@ -0,0 +1,327 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS // needed for *_MAX macros in dvdread headers +#endif + +#include "k3bvideodvd.h" + +#include + +#include + +#include + +#include // needed by dvdreads headers +#include +#include +#include + + +// I don't get this stuff, I should read something about VideoDVD some day... +#define CONVERT_TIME(x) (((x & 0xf0) >> 3) * 5 + (x & 0x0f)) +#define CONVERT_FRAME(x) (((x & 0x30) >> 3) * 5 + (x & 0x0f)) + + +K3bVideoDVD::VideoDVD::VideoDVD() +{ +} + + +K3bVideoDVD::VideoDVD::~VideoDVD() +{ +} + + +bool K3bVideoDVD::VideoDVD::valid() const +{ + return ( m_device != 0 ); +} + + +bool K3bVideoDVD::VideoDVD::open( K3bDevice::Device* dev ) +{ + m_device = 0; + m_titles.clear(); + + // + // Initialize libdvdread + // + dvd_reader_t* dvdReaderT = DVDOpen( QFile::encodeName(dev->blockDeviceName()) ); + if( !dvdReaderT ) { + kdDebug() << "(K3bVideoDVD) Could not open device " << dev->blockDeviceName() << endl; + return false; + } + + // + // Read volume id + // + char v[33]; + if( DVDUDFVolumeInfo( dvdReaderT, v, 33, 0, 0 ) != 0 && + DVDISOVolumeInfo( dvdReaderT, v, 33, 0, 0 ) != 0 ) { + kdDebug() << "(K3bVideoDVD) Could not read volume info." << endl; + DVDClose( dvdReaderT ); + return false; + } + m_volumeIdentifier = QString::fromLatin1( v, 32 ); + + // + // Open the VMG info + // + ifo_handle_t* vmg = ifoOpen( dvdReaderT, 0 ); + if( !vmg ) { + kdDebug() << "(K3bVideoDVD) Can't open VMG info." << endl; + DVDClose( dvdReaderT ); + return false; + } + + // + // parse titles + // + m_titles.resize( vmg->tt_srpt->nr_of_srpts ); + for( unsigned int i = 0; i < vmg->tt_srpt->nr_of_srpts; ++i ) { + title_info_t& title = vmg->tt_srpt->title[i]; + + // m_titles[i].m_videoDVD = this; + + // + // general title info + // + m_titles[i].m_titleNum = i+1; + m_titles[i].m_numPTTs = title.nr_of_ptts; + m_titles[i].m_numAngles = title.nr_of_angles; + m_titles[i].m_titleSet = title.title_set_nr; + m_titles[i].m_ttn = title.vts_ttn; + + // + // Open the title set the current title is a part of + // + ifo_handle_t* titleIfo = ifoOpen( dvdReaderT, vmg->tt_srpt->title[i].title_set_nr ); + if( !titleIfo ) { + kdDebug() << "(K3bVideoDVD) Can't open Title ifo." << endl; + ifoClose( vmg ); + DVDClose( dvdReaderT ); + return false; + } + + // + // Length of this title + // + // the program chain number of the first partoftitle of the current title (FIXME: but a title may contain multiple pgcs) + int pgc_id = titleIfo->vts_ptt_srpt->title[ m_titles[i].ttn() - 1 ].ptt[0].pgcn; + // (first?) program chain of the first partoftitle of the current title + pgc_t* cur_pgc = titleIfo->vts_pgcit->pgci_srp[ pgc_id - 1 ].pgc; + + m_titles[i].m_playbackTime = Time( CONVERT_TIME(cur_pgc->playback_time.hour), + CONVERT_TIME(cur_pgc->playback_time.minute), + CONVERT_TIME(cur_pgc->playback_time.second), + CONVERT_FRAME(cur_pgc->playback_time.frame_u) ); + + // + // Video stream information + // + m_titles[i].m_videoStream.m_permittedDf = titleIfo->vtsi_mat->vts_video_attr.permitted_df; + m_titles[i].m_videoStream.m_displayAspectRatio = titleIfo->vtsi_mat->vts_video_attr.display_aspect_ratio; + m_titles[i].m_videoStream.m_videoFormat = titleIfo->vtsi_mat->vts_video_attr.video_format; + m_titles[i].m_videoStream.m_mpegVersion = titleIfo->vtsi_mat->vts_video_attr.mpeg_version; + m_titles[i].m_videoStream.m_filmMode = titleIfo->vtsi_mat->vts_video_attr.film_mode; + m_titles[i].m_videoStream.m_letterboxed = titleIfo->vtsi_mat->vts_video_attr.letterboxed; + m_titles[i].m_videoStream.m_pictureSize = titleIfo->vtsi_mat->vts_video_attr.picture_size; + m_titles[i].m_videoStream.m_bitRate = titleIfo->vtsi_mat->vts_video_attr.bit_rate; + + // + // Audio stream information + // + m_titles[i].m_audioStreams.resize( titleIfo->vtsi_mat->nr_of_vts_audio_streams ); + for( unsigned int j = 0; j < titleIfo->vtsi_mat->nr_of_vts_audio_streams; ++j ) { + m_titles[i].m_audioStreams[j].m_format = titleIfo->vtsi_mat->vts_audio_attr[j].audio_format; + m_titles[i].m_audioStreams[j].m_applicationMode = titleIfo->vtsi_mat->vts_audio_attr[j].application_mode; + m_titles[i].m_audioStreams[j].m_quantization = titleIfo->vtsi_mat->vts_audio_attr[j].quantization; + m_titles[i].m_audioStreams[j].m_sampleFrequency = titleIfo->vtsi_mat->vts_audio_attr[j].sample_frequency; + m_titles[i].m_audioStreams[j].m_codeExtension = titleIfo->vtsi_mat->vts_audio_attr[j].code_extension; + m_titles[i].m_audioStreams[j].m_multiChannelExt = titleIfo->vtsi_mat->vts_audio_attr[j].multichannel_extension; + m_titles[i].m_audioStreams[j].m_channels = titleIfo->vtsi_mat->vts_audio_attr[j].channels+1; + if( titleIfo->vtsi_mat->vts_audio_attr[j].lang_type == 1 ) + m_titles[i].m_audioStreams[j].m_langCode.sprintf( "%c%c", + titleIfo->vtsi_mat->vts_audio_attr[j].lang_code>>8, + titleIfo->vtsi_mat->vts_audio_attr[j].lang_code & 0xff ); + else + m_titles[i].m_audioStreams[j].m_langCode = QString::null; + } + + // + // SubPicture stream information + // + m_titles[i].m_subPictureStreams.resize( titleIfo->vtsi_mat->nr_of_vts_subp_streams ); + for( unsigned int j = 0; j < titleIfo->vtsi_mat->nr_of_vts_subp_streams; ++j ) { + m_titles[i].m_subPictureStreams[j].m_codeMode = titleIfo->vtsi_mat->vts_subp_attr[j].code_mode; + m_titles[i].m_subPictureStreams[j].m_codeExtension = titleIfo->vtsi_mat->vts_subp_attr[j].code_extension; + if( titleIfo->vtsi_mat->vts_subp_attr[j].type == 1 ) + m_titles[i].m_subPictureStreams[j].m_langCode.sprintf( "%c%c", + titleIfo->vtsi_mat->vts_subp_attr[j].lang_code>>8, + titleIfo->vtsi_mat->vts_subp_attr[j].lang_code & 0xff ); + else + m_titles[i].m_subPictureStreams[j].m_langCode = QString::null; + } + + // + // add chapter info + // + m_titles[i].m_ptts.resize( m_titles[i].numPTTs() ); + for( unsigned int j = 0; j < m_titles[i].numPTTs(); ++j ) { + m_titles[i].m_ptts[j].m_pttNum = j+1; + m_titles[i].m_ptts[j].m_playbackTime = Time( CONVERT_TIME(cur_pgc->cell_playback[j].playback_time.hour), + CONVERT_TIME(cur_pgc->cell_playback[j].playback_time.minute), + CONVERT_TIME(cur_pgc->cell_playback[j].playback_time.second), + CONVERT_FRAME(cur_pgc->cell_playback[j].playback_time.frame_u) ); + m_titles[i].m_ptts[j].m_firstSector = cur_pgc->cell_playback[j].first_sector; + m_titles[i].m_ptts[j].m_lastSector = cur_pgc->cell_playback[j].last_sector; + } + + ifoClose( titleIfo ); + } + + ifoClose( vmg ); + DVDClose( dvdReaderT ); + + // + // Setting the device makes this a valid instance + // + m_device = dev; + + return true; +} + + +const K3bVideoDVD::Title& K3bVideoDVD::VideoDVD::title( unsigned int num ) const +{ + return m_titles[num]; +} + + +const K3bVideoDVD::Title& K3bVideoDVD::VideoDVD::operator[]( unsigned int num ) const +{ + return title( num ); +} + + +void K3bVideoDVD::VideoDVD::debug() const +{ + kdDebug() << "VideoDVD information:" << endl + << "=====================" << endl + << "Volume ID: " << volumeIdentifier() << endl << endl; + + for( unsigned int i = 0; i < numTitles(); ++i ) { + kdDebug() << "Title " << title(i).titleNumber() << " (" << title(i).playbackTime().toString() << ")" << endl + << " Chapters: " << title(i).numPTTs() << endl + << " Angles: " << title(i).numAngles() << endl + << " VTS,TTN: " << title(i).titleSet() << "," << title(i).ttn() << endl + << " Audio Streams:" << endl; + for( unsigned int j = 0; j < title(i).numAudioStreams(); ++j ) + kdDebug() << " " << title(i).audioStream(j).langCode() << ": " + << audioFormatString( title(i).audioStream(j).format() ) << ", " + << audioCodeExtensionString( title(i).audioStream(j).codeExtension() ) << endl; + kdDebug() << " SubPicture Streams:" << endl; + for( unsigned int j = 0; j < title(i).numSubPictureStreams(); ++j ) + kdDebug() << " " << title(i).subPictureStream(j).langCode() << ": " + << subPictureCodeModeString( title(i).subPictureStream(j).codeMode() ) << ", " + << subPictureCodeExtensionString( title(i).subPictureStream(j).codeExtension() ) << endl; + } +} + + +QString K3bVideoDVD::audioFormatString( int format ) +{ + switch( format ) { + case AUDIO_FORMAT_AC3: + return i18n("AC3"); + case AUDIO_FORMAT_MPEG1: + return i18n("MPEG1"); + case AUDIO_FORMAT_MPEG2EXT: + return i18n("MPEG2 Extended"); + case AUDIO_FORMAT_LPCM: + return i18n("LPCM"); + case AUDIO_FORMAT_DTS: + return i18n("DTS"); + default: + return i18n("unknown audio format"); + } +} + + +QString K3bVideoDVD::audioCodeExtensionString( int ext ) +{ + switch( ext ) { + case AUDIO_CODE_EXT_UNSPECIFIED: + return i18n("Unspecified"); + case AUDIO_CODE_EXT_NORMAL: + return i18n("Normal"); + case AUDIO_CODE_EXT_VISUALLY_IMPAIRED: + return i18n("For the visually impaired"); + case AUDIO_CODE_EXT_DIR_COMMENTS_1: + return i18n("Director's comments 1"); + case AUDIO_CODE_EXT_DIR_COMMENTS_2: + return i18n("Director's comments 2"); + default: + return i18n("unknown audio code extension"); + } +} + + +QString K3bVideoDVD::subPictureCodeModeString( int mode ) +{ + switch( mode ) { + case SUBPIC_CODE_MODE_RLE: + return i18n("RLE"); + case SUBPIC_CODE_MODE_EXT: + return i18n("Extended"); + default: + return i18n("unknown coding mode"); + } +} + + +QString K3bVideoDVD::subPictureCodeExtensionString( int ext ) +{ + switch( ext ) { + case SUBPIC_CODE_EXT_UNSPECIFIED: + return i18n("Unspecified"); + case SUBPIC_CODE_EXT_CAPTION_NORMAL_SIZE: + return i18n("Caption with normal size character"); + case SUBPIC_CODE_EXT_CAPTION_BIGGER_SIZE: + return i18n("Caption with bigger size character"); + case SUBPIC_CODE_EXT_CAPTION_FOR_CHILDREN: + return i18n("Caption for children"); + case SUBPIC_CODE_EXT_CLOSED_CAPTION_NORMAL_SIZE: + return i18n("Closed caption with normal size character"); + case SUBPIC_CODE_EXT_CLOSED_CAPTION_BIGGER_SIZE: + return i18n("Closed caption with bigger size character"); + case SUBPIC_CODE_EXT_CLOSED_CAPTION_FOR_CHILDREN: + return i18n("Closed caption for children"); + case SUBPIC_CODE_EXT_FORCED_CAPTION: + return i18n("Forced caption"); + case SUBPIC_CODE_EXT_DIR_COMMENTS_NORMAL_SIZE: + return i18n("Director's comments with normal size characters"); + case SUBPIC_CODE_EXT_DIR_COMMENTS_BIGGER_SIZE: + return i18n("Director's comments with bigger size characters"); + case SUBPIC_CODE_EXT_DIR_COMMENTS_FOR_CHILDREN: + return i18n("Director's comments for children"); + default: + return i18n("unknown code extension"); + } +} + diff --git a/libk3b/videodvd/k3bvideodvd.h b/libk3b/videodvd/k3bvideodvd.h new file mode 100644 index 0000000..180a6f5 --- /dev/null +++ b/libk3b/videodvd/k3bvideodvd.h @@ -0,0 +1,91 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VIDEOVD_H_ +#define _K3B_VIDEOVD_H_ + +#include + +#include + +#include +#include + + +namespace K3bDevice { + class Device; +} + +/** + * The K3bVideoDVD classes do not provide a complete playback frontend to + * libdvdread but are merely intended for Video DVD analysis. + * + * They are title based and thus treat a Video DVD to be a set of titles. + * Additional Video DVD constructs such as title sets, parts of titles (chapters), + * program chanins, or cells are not handled explicitly. + * + * The usage is very simple. One creates a VideoDVD instance and calls the open() + * method with a device containing a Video DVD. If the method returns true the + * analysis was successful and the structures are filled. + * + * After open() has returned the device has already been closed. + */ +namespace K3bVideoDVD +{ + /** + * libdvdread wrapper class + */ + class LIBK3B_EXPORT VideoDVD + { + public: + VideoDVD(); + ~VideoDVD(); + + /** + * \return true if a Video DVD was successfully opened via open() + */ + bool valid() const; + + /** + * Open a video dvd and parse it's contents. The device will be closed after this + * method returns, regardless of it's success. + */ + bool open( K3bDevice::Device* dev ); + + K3bDevice::Device* device() const { return m_device; } + const QString& volumeIdentifier() const { return m_volumeIdentifier; } + unsigned int numTitles() const { return m_titles.count(); } + + /** + * Get a title from the Video DVD. Index starts at 0. + */ + const Title& title( unsigned int num ) const; + const Title& operator[]( unsigned int num ) const; + + void debug() const; + + private: + K3bDevice::Device* m_device; + QValueVector m_titles; + QString m_volumeIdentifier; + }; + + LIBK3B_EXPORT QString audioFormatString( int format ); + LIBK3B_EXPORT QString audioCodeExtensionString( int ext ); + LIBK3B_EXPORT QString subPictureCodeModeString( int mode ); + LIBK3B_EXPORT QString subPictureCodeExtensionString( int ext ); +} + +#endif diff --git a/libk3b/videodvd/k3bvideodvdaudiostream.h b/libk3b/videodvd/k3bvideodvdaudiostream.h new file mode 100644 index 0000000..78068f0 --- /dev/null +++ b/libk3b/videodvd/k3bvideodvdaudiostream.h @@ -0,0 +1,112 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VIDEODVD_AUDIO_STREAM_H_ +#define _K3B_VIDEODVD_AUDIO_STREAM_H_ + +#include <k3b_export.h> + +#include <qstring.h> + + +namespace K3bVideoDVD +{ + enum AudioFormat { + AUDIO_FORMAT_AC3 = 0, + AUDIO_FORMAT_MPEG1 = 2, + AUDIO_FORMAT_MPEG2EXT = 3, + AUDIO_FORMAT_LPCM = 4, + AUDIO_FORMAT_DTS = 6 + }; + + enum AudioApplicationMode { + AUDIO_APPLICATION_KARAOKE = 1, + AUDIO_APPLICATION_SURROUND = 2 + }; + + enum AudioQuantization { + AUDIO_QUANTIZATION_16BIT = 0, + AUDIO_QUANTIZATION_20BIT = 1, + AUDIO_QUANTIZATION_24BIT = 2 + }; + + enum AudioSampleFrequency { + AUDIO_SAMPLE_FREQ_48HZ = 0, + AUDIO_SAMPLE_FREQ_96HZ = 1 + }; + + enum AudioCodeExtension { + AUDIO_CODE_EXT_UNSPECIFIED = 0, + AUDIO_CODE_EXT_NORMAL = 1, + AUDIO_CODE_EXT_VISUALLY_IMPAIRED = 2, + AUDIO_CODE_EXT_DIR_COMMENTS_1 = 3, + AUDIO_CODE_EXT_DIR_COMMENTS_2 = 4 + }; + + class LIBK3B_EXPORT AudioStream + { + public: + AudioStream() {} + + /** + * \return A two chars language code or the empty string + * if the language is undefined. + */ + const QString& langCode() const { return m_langCode; } + + /** + * \see AudioFormat + */ + unsigned short format() const { return m_format; } + + /** + * \see AudioApplicationMode + */ + unsigned short applicationMode() const { return m_applicationMode; } + + /** + * \see AudioQuantization + */ + unsigned short quantization() const { return m_quantization; } + + /** + * \see AudioSampleFrequency + */ + unsigned short sampleFrequency() const { return m_sampleFrequency; } + + /** + * \see AudioCodeExtension + */ + unsigned short codeExtension() const { return m_codeExtension; } + + bool multiChannelExt() const { return m_multiChannelExt; } + + unsigned short channels() const { return m_channels; } + + private: + unsigned short m_format:3; + unsigned short m_applicationMode:2; + unsigned short m_quantization:2; + unsigned short m_sampleFrequency:2; + unsigned short m_codeExtension; + bool m_multiChannelExt; + unsigned short m_channels:3; + QString m_langCode; + + friend class VideoDVD; + }; +} + +#endif diff --git a/libk3b/videodvd/k3bvideodvdptt.h b/libk3b/videodvd/k3bvideodvdptt.h new file mode 100644 index 0000000..f0dca91 --- /dev/null +++ b/libk3b/videodvd/k3bvideodvdptt.h @@ -0,0 +1,50 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VIDEODVD_PTT_H_ +#define _K3B_VIDEODVD_PTT_H_ + +#include <k3b_export.h> + +#include <k3bvideodvd.h> +#include <k3bvideodvdtime.h> + + +namespace K3bVideoDVD +{ + class LIBK3B_EXPORT PTT + { + public: + PTT() {} + + unsigned int pttNumber() const { return m_pttNum; } + + const Time& playbackTime() const { return m_playbackTime; } + + unsigned int firstSector() const { return m_firstSector; } + unsigned int lastSector() const { return m_lastSector; } + + private: + unsigned int m_pttNum; + Time m_playbackTime; + + unsigned int m_firstSector; + unsigned int m_lastSector; + + friend class VideoDVD; + }; +} + +#endif diff --git a/libk3b/videodvd/k3bvideodvdsubpicturestream.h b/libk3b/videodvd/k3bvideodvdsubpicturestream.h new file mode 100644 index 0000000..b32407d --- /dev/null +++ b/libk3b/videodvd/k3bvideodvdsubpicturestream.h @@ -0,0 +1,68 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VIDEODVD_SUBPICTURE_STREAM_H_ +#define _K3B_VIDEODVD_SUBPICTURE_STREAM_H_ + +#include <k3b_export.h> + +#include <qstring.h> + + +namespace K3bVideoDVD +{ + enum SubPictureCodeMode { + SUBPIC_CODE_MODE_RLE = 0, + SUBPIC_CODE_MODE_EXT = 1 + }; + + enum SubPictureCodeExtension { + SUBPIC_CODE_EXT_UNSPECIFIED = 0, + SUBPIC_CODE_EXT_CAPTION_NORMAL_SIZE = 1, + SUBPIC_CODE_EXT_CAPTION_BIGGER_SIZE = 2, + SUBPIC_CODE_EXT_CAPTION_FOR_CHILDREN = 3, + SUBPIC_CODE_EXT_CLOSED_CAPTION_NORMAL_SIZE = 5, + SUBPIC_CODE_EXT_CLOSED_CAPTION_BIGGER_SIZE = 6, + SUBPIC_CODE_EXT_CLOSED_CAPTION_FOR_CHILDREN = 7, + SUBPIC_CODE_EXT_FORCED_CAPTION = 9, + SUBPIC_CODE_EXT_DIR_COMMENTS_NORMAL_SIZE = 13, + SUBPIC_CODE_EXT_DIR_COMMENTS_BIGGER_SIZE = 14, + SUBPIC_CODE_EXT_DIR_COMMENTS_FOR_CHILDREN = 15 + }; + + class LIBK3B_EXPORT SubPictureStream + { + public: + SubPictureStream() {} + + unsigned int codeMode() const { return m_codeMode; } + unsigned int codeExtension() const { return m_codeExtension; } + + /** + * \return A two chars language code or the empty string + * if the language is undefined. + */ + const QString& langCode() const { return m_langCode; } + + private: + unsigned int m_codeMode:3; + QString m_langCode; + unsigned int m_codeExtension; + + friend class VideoDVD; + }; +} + +#endif diff --git a/libk3b/videodvd/k3bvideodvdtime.cpp b/libk3b/videodvd/k3bvideodvdtime.cpp new file mode 100644 index 0000000..acc6aec --- /dev/null +++ b/libk3b/videodvd/k3bvideodvdtime.cpp @@ -0,0 +1,106 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bvideodvdtime.h" + +K3bVideoDVD::Time::Time() + : m_hour(0), + m_minute(0), + m_second(0), + m_frame(0) +{ +} + + +K3bVideoDVD::Time::Time( unsigned short hour, + unsigned short min, + unsigned short sec, + unsigned short frame ) + : m_hour(hour), + m_minute(min), + m_second(sec), + m_frame(frame) +{ +} + + +double K3bVideoDVD::Time::totalSeconds() const +{ + double s = (double)second(); + s += 60.0 * (double)minute(); + s += 3600.0 * (double)hour(); + + return s + (double)( frame() / frameRate() ); +} + + +unsigned int K3bVideoDVD::Time::totalFrames() const +{ + double f = (double)second(); + f += 60.0 * (double)minute(); + f += 3600.0 * (double)hour(); + + return (int)( f * frameRate() ) + frame(); +} + + +double K3bVideoDVD::Time::frameRate() const +{ + // + // This is how it is done in libdvdread + // I don't really understand it, though... :( + // + switch( (frame() & 0xc0) >> 6 ) { + case 1: + // PAL? + return 25.0; + case 3: + // NTSC? + return 29.97; + default: + // should only happen for time == 0? + return 0.0; + } +} + + +QString K3bVideoDVD::Time::toString( bool includeFrames ) const +{ + // FIXME: use a d-pointer + const_cast<K3bVideoDVD::Time*>(this)->makeValid(); + + if( includeFrames ) + return QString().sprintf( "%02d:%02d:%02d.%02d", + m_hour, + m_minute, + m_second, + m_frame & 0x3f ); + else + return QString().sprintf( "%02d:%02d:%02d", + m_hour, + m_minute, + m_second + ( m_frame > 0 ? 1 : 0 ) ); +} + + +void K3bVideoDVD::Time::makeValid() +{ + // FIXME: how to handle the frames? + + m_minute += m_second/60; + m_second = m_second % 60; + m_hour += m_minute/60; + m_minute = m_minute % 60; +} diff --git a/libk3b/videodvd/k3bvideodvdtime.h b/libk3b/videodvd/k3bvideodvdtime.h new file mode 100644 index 0000000..f486741 --- /dev/null +++ b/libk3b/videodvd/k3bvideodvdtime.h @@ -0,0 +1,59 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VIDEODVD_TIME_H_ +#define _K3B_VIDEODVD_TIME_H_ + +#include <k3b_export.h> + +#include <qstring.h> + +/** + * This should not be confused with K3b::Msf + */ +namespace K3bVideoDVD +{ + class LIBK3B_EXPORT Time + { + public: + Time(); + Time( unsigned short hour, + unsigned short min, + unsigned short sec, + unsigned short frame ); + + unsigned short hour() const { return m_hour; } + unsigned short minute() const { return m_minute; } + unsigned short second() const { return m_second; } + unsigned short frame() const { return m_frame; } + + double totalSeconds() const; + unsigned int totalFrames() const; + + // FIXME: is this useful? + double frameRate() const; + + QString toString( bool includeFrames = true ) const; + + private: + void makeValid(); + + unsigned int m_hour; + unsigned int m_minute; + unsigned int m_second; + unsigned int m_frame; + }; + } +#endif diff --git a/libk3b/videodvd/k3bvideodvdtitle.h b/libk3b/videodvd/k3bvideodvdtitle.h new file mode 100644 index 0000000..17f31a3 --- /dev/null +++ b/libk3b/videodvd/k3bvideodvdtitle.h @@ -0,0 +1,112 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VIDEODVD_TITLE_H_ +#define _K3B_VIDEODVD_TITLE_H_ + +#include <k3b_export.h> + +#include <k3bvideodvdtime.h> +#include <k3bvideodvdvideostream.h> +#include <k3bvideodvdaudiostream.h> +#include <k3bvideodvdsubpicturestream.h> +#include <k3bvideodvdptt.h> + +#include <qvaluevector.h> + + +namespace K3bVideoDVD +{ + class LIBK3B_EXPORT Title + { + public: + Title() {} + + unsigned int titleNumber() const { return m_titleNum; } + + /** + * \return The number of PTTs (Part of Title), commonly known + * as chapters + */ + unsigned int numPTTs() const { return m_numPTTs; } + + /** + * This method is just here for convenience. It returns the same as the above. + */ + unsigned int numChapters() const { return m_numPTTs; } + unsigned int numAngles() const { return m_numAngles; } + + /** + * \return The number of the titleset this title is a part of. + */ + unsigned int titleSet() const { return m_titleSet; } + + /** + * \return Number of the title in it's titleset. + */ + unsigned int ttn() const { return m_ttn; } + + unsigned int numAudioStreams() const { return m_audioStreams.count(); } + unsigned int numSubPictureStreams() const { return m_subPictureStreams.count(); } + + const VideoStream& videoStream() const { return m_videoStream; } + const AudioStream& audioStream( unsigned int i ) const { return m_audioStreams[i]; } + const SubPictureStream& subPictureStream( unsigned int i ) const { return m_subPictureStreams[i]; } + + /** + * Access to the PTTs of the title + */ + const PTT& operator[]( int i ) const { return ptt( i ); } + + /** + * Access to the PTTs of the title + */ + const PTT& ptt( int i ) const { return m_ptts[i]; } + + /** + * Access to the PTTs (chapters) of the title + */ + const PTT& chapter( int i ) const { return ptt( i ); } + + const Time& playbackTime() const { return m_playbackTime; } + + /** + * \return A video capture + */ + // QBitmap videoCapture( const Time& ) const; + + private: + unsigned int m_titleNum; + unsigned int m_numPTTs; + unsigned int m_titleSet; + // FIXME: find a proper name for ttn + unsigned int m_ttn; + unsigned int m_numAngles; + + Time m_playbackTime; + + VideoStream m_videoStream; + QValueVector<AudioStream> m_audioStreams; + QValueVector<SubPictureStream> m_subPictureStreams; + + QValueVector<PTT> m_ptts; + + // VideoDVD* m_videoDVD; + + friend class VideoDVD; + }; +} + +#endif diff --git a/libk3b/videodvd/k3bvideodvdvideostream.cpp b/libk3b/videodvd/k3bvideodvdvideostream.cpp new file mode 100644 index 0000000..e7b6e9e --- /dev/null +++ b/libk3b/videodvd/k3bvideodvdvideostream.cpp @@ -0,0 +1,60 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bvideodvdvideostream.h" + +unsigned int K3bVideoDVD::VideoStream::pictureWidth() const +{ + switch( pictureSize() ) { + case VIDEO_PICTURE_SIZE_720: + return 720; + case VIDEO_PICTURE_SIZE_704: + return 704; + case VIDEO_PICTURE_SIZE_352: + case VIDEO_PICTURE_SIZE_352_2: + return 352; + default: + return 0; + } +} + + +unsigned int K3bVideoDVD::VideoStream::pictureHeight() const +{ + int height = 480; + if( format() != 0 ) + height = 576; + if( pictureSize() == VIDEO_PICTURE_SIZE_352_2 ) + height /= 2; + + return height; +} + + +unsigned int K3bVideoDVD::VideoStream::realPictureWidth() const +{ + double aspectRatio = 0.0; + if( displayAspectRatio() == K3bVideoDVD::VIDEO_ASPECT_RATIO_4_3 ) + aspectRatio = 4.0/3.0; + else + aspectRatio = 16.0/9.0; + return (int)(aspectRatio * (double)realPictureHeight()); +} + + +unsigned int K3bVideoDVD::VideoStream::realPictureHeight() const +{ + return pictureHeight(); +} diff --git a/libk3b/videodvd/k3bvideodvdvideostream.h b/libk3b/videodvd/k3bvideodvdvideostream.h new file mode 100644 index 0000000..c6c9d95 --- /dev/null +++ b/libk3b/videodvd/k3bvideodvdvideostream.h @@ -0,0 +1,107 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_VIDEODVD_VIDEO_STREAM_H_ +#define _K3B_VIDEODVD_VIDEO_STREAM_H_ + +#include <k3b_export.h> + +namespace K3bVideoDVD +{ + enum VideoMPEGVersion { + MPEG1 = 0, + MPEG2 = 1 + }; + + enum VideoFormat { + VIDEO_FORMAT_NTSC = 0, + VIDEO_FORMAT_PAL = 1 + }; + + enum VideoAspectRatio { + VIDEO_ASPECT_RATIO_4_3 = 0, + VIDEO_ASPECT_RATIO_16_9 = 1 + }; + + enum VideoPermitedDf { + VIDEO_PERMITTED_DF_BOTH = 0, + VIDEO_PERMITTED_DF_PAN_SCAN = 1, + VIDEO_PERMITTED_DF_LETTERBOXED = 2, + VIDEO_PERMITTED_DF_UNSPECIFIED = 3 + }; + + enum VideoBitRate { + VIDEO_BITRATE_VARIABLE = 0, + VIDEO_BITRATE_CONSTANT = 1 + }; + + enum VideoPicureSize { + VIDEO_PICTURE_SIZE_720 = 0, + VIDEO_PICTURE_SIZE_704 = 1, + VIDEO_PICTURE_SIZE_352 = 2, + VIDEO_PICTURE_SIZE_352_2 = 3 + }; + + class LIBK3B_EXPORT VideoStream + { + public: + VideoStream() {} + + unsigned int permittedDf() const { return m_permittedDf; } + unsigned int displayAspectRatio() const { return m_displayAspectRatio; } + unsigned int format() const { return m_videoFormat; } + unsigned int mpegVersion() const { return m_mpegVersion; } + unsigned int filmMode() const { return m_filmMode; } + unsigned int letterboxed() const { return m_letterboxed; } + unsigned int pictureSize() const { return m_pictureSize; } + unsigned int bitRate() const { return m_bitRate; } + + /** + * The picture width of the video stream + */ + unsigned int pictureWidth() const; + + /** + * The picture height of the video stream + */ + unsigned int pictureHeight() const; + + /** + * The width of the "real" video after applying aspect ratio + * correction + */ + unsigned int realPictureWidth() const; + + /** + * The height of the "real" video after applying aspect ratio + * correction + */ + unsigned int realPictureHeight() const; + + private: + unsigned int m_permittedDf:2; + unsigned int m_displayAspectRatio:2; + unsigned int m_videoFormat:2; + unsigned int m_mpegVersion:2; + unsigned int m_filmMode:1; + unsigned int m_letterboxed:1; + unsigned int m_pictureSize:2; + unsigned int m_bitRate:1; + + friend class VideoDVD; + }; +} + +#endif -- cgit v1.2.1