summaryrefslogtreecommitdiffstats
path: root/libk3b
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:15:56 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:15:56 +0000
commit50b48aec6ddd451a6d1709c0942477b503457663 (patch)
treea9ece53ec06fd0a2819de7a2a6de997193566626 /libk3b
downloadk3b-50b48aec6ddd451a6d1709c0942477b503457663.tar.gz
k3b-50b48aec6ddd451a6d1709c0942477b503457663.zip
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
Diffstat (limited to 'libk3b')
-rw-r--r--libk3b/Makefile.am28
-rw-r--r--libk3b/README29
-rw-r--r--libk3b/cddb/Makefile.am9
-rw-r--r--libk3b/cddb/k3bcddb.cpp280
-rw-r--r--libk3b/cddb/k3bcddb.h103
-rw-r--r--libk3b/cddb/k3bcddbhttpquery.cpp233
-rw-r--r--libk3b/cddb/k3bcddbhttpquery.h64
-rw-r--r--libk3b/cddb/k3bcddblocalquery.cpp129
-rw-r--r--libk3b/cddb/k3bcddblocalquery.h48
-rw-r--r--libk3b/cddb/k3bcddblocalsubmit.cpp102
-rw-r--r--libk3b/cddb/k3bcddblocalsubmit.h43
-rw-r--r--libk3b/cddb/k3bcddbmultientriesdialog.cpp74
-rw-r--r--libk3b/cddb/k3bcddbmultientriesdialog.h48
-rw-r--r--libk3b/cddb/k3bcddbpquery.cpp278
-rw-r--r--libk3b/cddb/k3bcddbpquery.h62
-rw-r--r--libk3b/cddb/k3bcddbquery.cpp275
-rw-r--r--libk3b/cddb/k3bcddbquery.h115
-rw-r--r--libk3b/cddb/k3bcddbresult.cpp49
-rw-r--r--libk3b/cddb/k3bcddbresult.h79
-rw-r--r--libk3b/cddb/k3bcddbsubmit.cpp84
-rw-r--r--libk3b/cddb/k3bcddbsubmit.h60
-rw-r--r--libk3b/configure.in.in3
-rw-r--r--libk3b/core/Makefile.am19
-rw-r--r--libk3b/core/k3b_export.h33
-rw-r--r--libk3b/core/k3bcore.cpp375
-rw-r--r--libk3b/core/k3bcore.h181
-rw-r--r--libk3b/core/k3bdataevent.h48
-rw-r--r--libk3b/core/k3bdefaultexternalprograms.cpp1030
-rw-r--r--libk3b/core/k3bdefaultexternalprograms.h143
-rw-r--r--libk3b/core/k3bexternalbinmanager.cpp389
-rw-r--r--libk3b/core/k3bexternalbinmanager.h162
-rw-r--r--libk3b/core/k3bglobals.cpp634
-rw-r--r--libk3b/core/k3bglobals.h257
-rw-r--r--libk3b/core/k3bglobalsettings.cpp61
-rw-r--r--libk3b/core/k3bglobalsettings.h70
-rw-r--r--libk3b/core/k3bjob.cpp253
-rw-r--r--libk3b/core/k3bjob.h311
-rw-r--r--libk3b/core/k3bjobhandler.h64
-rw-r--r--libk3b/core/k3bprocess.cpp452
-rw-r--r--libk3b/core/k3bprocess.h204
-rw-r--r--libk3b/core/k3bprogressinfoevent.h85
-rw-r--r--libk3b/core/k3bsimplejobhandler.cpp62
-rw-r--r--libk3b/core/k3bsimplejobhandler.h61
-rw-r--r--libk3b/core/k3bthread.cpp221
-rw-r--r--libk3b/core/k3bthread.h95
-rw-r--r--libk3b/core/k3bthreadjob.cpp161
-rw-r--r--libk3b/core/k3bthreadjob.h89
-rw-r--r--libk3b/core/k3bversion.cpp318
-rw-r--r--libk3b/core/k3bversion.h141
-rw-r--r--libk3b/dummy.cpp1
-rw-r--r--libk3b/jobs/Makefile.am43
-rw-r--r--libk3b/jobs/k3baudiocuefilewritingjob.cpp272
-rw-r--r--libk3b/jobs/k3baudiocuefilewritingjob.h79
-rw-r--r--libk3b/jobs/k3baudiosessionreadingjob.cpp278
-rw-r--r--libk3b/jobs/k3baudiosessionreadingjob.h75
-rw-r--r--libk3b/jobs/k3bbinimagewritingjob.cpp234
-rw-r--r--libk3b/jobs/k3bbinimagewritingjob.h79
-rw-r--r--libk3b/jobs/k3bblankingjob.cpp176
-rw-r--r--libk3b/jobs/k3bblankingjob.h71
-rw-r--r--libk3b/jobs/k3bcdcopyjob.cpp1213
-rw-r--r--libk3b/jobs/k3bcdcopyjob.h117
-rw-r--r--libk3b/jobs/k3bcdda2wavreader.cpp254
-rw-r--r--libk3b/jobs/k3bcdda2wavreader.h70
-rw-r--r--libk3b/jobs/k3bclonejob.cpp375
-rw-r--r--libk3b/jobs/k3bclonejob.h99
-rw-r--r--libk3b/jobs/k3bclonetocreader.cpp235
-rw-r--r--libk3b/jobs/k3bclonetocreader.h45
-rw-r--r--libk3b/jobs/k3bdatatrackreader.cpp515
-rw-r--r--libk3b/jobs/k3bdatatrackreader.h87
-rw-r--r--libk3b/jobs/k3bdvdcopyjob.cpp894
-rw-r--r--libk3b/jobs/k3bdvdcopyjob.h99
-rw-r--r--libk3b/jobs/k3bdvdformattingjob.cpp536
-rw-r--r--libk3b/jobs/k3bdvdformattingjob.h91
-rw-r--r--libk3b/jobs/k3biso9660imagewritingjob.cpp458
-rw-r--r--libk3b/jobs/k3biso9660imagewritingjob.h98
-rw-r--r--libk3b/jobs/k3breadcdreader.cpp335
-rw-r--r--libk3b/jobs/k3breadcdreader.h91
-rw-r--r--libk3b/jobs/k3bverificationjob.cpp384
-rw-r--r--libk3b/jobs/k3bverificationjob.h92
-rw-r--r--libk3b/jobs/k3bvideodvdtitledetectclippingjob.cpp291
-rw-r--r--libk3b/jobs/k3bvideodvdtitledetectclippingjob.h106
-rw-r--r--libk3b/jobs/k3bvideodvdtitletranscodingjob.cpp583
-rw-r--r--libk3b/jobs/k3bvideodvdtitletranscodingjob.h275
-rw-r--r--libk3b/k3bimage.xsd175
-rw-r--r--libk3b/plugin/Makefile.am28
-rw-r--r--libk3b/plugin/k3baudioclient.cpp46
-rw-r--r--libk3b/plugin/k3baudioclient.h51
-rw-r--r--libk3b/plugin/k3baudiodecoder.cpp599
-rw-r--r--libk3b/plugin/k3baudiodecoder.h254
-rw-r--r--libk3b/plugin/k3baudioencoder.cpp175
-rw-r--r--libk3b/plugin/k3baudioencoder.h203
-rw-r--r--libk3b/plugin/k3baudiooutputplugin.h69
-rw-r--r--libk3b/plugin/k3baudioserver.cpp214
-rw-r--r--libk3b/plugin/k3baudioserver.h85
-rw-r--r--libk3b/plugin/k3bplugin.cpp36
-rw-r--r--libk3b/plugin/k3bplugin.h113
-rw-r--r--libk3b/plugin/k3bpluginconfigwidget.cpp48
-rw-r--r--libk3b/plugin/k3bpluginconfigwidget.h40
-rw-r--r--libk3b/plugin/k3bpluginfactory.cpp33
-rw-r--r--libk3b/plugin/k3bpluginfactory.h98
-rw-r--r--libk3b/plugin/k3bpluginmanager.cpp189
-rw-r--r--libk3b/plugin/k3bpluginmanager.h70
-rw-r--r--libk3b/plugin/k3bprojectplugin.h161
-rw-r--r--libk3b/plugin/libsamplerate/Makefile.am20
-rw-r--r--libk3b/plugin/libsamplerate/common.h105
-rw-r--r--libk3b/plugin/libsamplerate/configure.in.in13
-rw-r--r--libk3b/plugin/libsamplerate/fastest_coeffs.h2493
-rw-r--r--libk3b/plugin/libsamplerate/float_cast.h203
-rw-r--r--libk3b/plugin/libsamplerate/high_qual_coeffs.h17116
-rw-r--r--libk3b/plugin/libsamplerate/mid_qual_coeffs.h5315
-rw-r--r--libk3b/plugin/libsamplerate/samplerate.c301
-rw-r--r--libk3b/plugin/libsamplerate/samplerate.h138
-rw-r--r--libk3b/plugin/libsamplerate/src_linear.c194
-rw-r--r--libk3b/plugin/libsamplerate/src_sinc.c471
-rw-r--r--libk3b/plugin/libsamplerate/src_zoh.c186
-rw-r--r--libk3b/projects/Makefile.am32
-rw-r--r--libk3b/projects/audiocd/Makefile.am35
-rw-r--r--libk3b/projects/audiocd/k3baudiocdtrackdrag.cpp109
-rw-r--r--libk3b/projects/audiocd/k3baudiocdtrackdrag.h50
-rw-r--r--libk3b/projects/audiocd/k3baudiocdtracksource.cpp262
-rw-r--r--libk3b/projects/audiocd/k3baudiocdtracksource.h99
-rw-r--r--libk3b/projects/audiocd/k3baudiodatasource.cpp210
-rw-r--r--libk3b/projects/audiocd/k3baudiodatasource.h168
-rw-r--r--libk3b/projects/audiocd/k3baudiodatasourceiterator.cpp71
-rw-r--r--libk3b/projects/audiocd/k3baudiodatasourceiterator.h61
-rw-r--r--libk3b/projects/audiocd/k3baudiodoc.cpp1127
-rw-r--r--libk3b/projects/audiocd/k3baudiodoc.h263
-rw-r--r--libk3b/projects/audiocd/k3baudiofile.cpp112
-rw-r--r--libk3b/projects/audiocd/k3baudiofile.h85
-rw-r--r--libk3b/projects/audiocd/k3baudioimager.cpp203
-rw-r--r--libk3b/projects/audiocd/k3baudioimager.h59
-rw-r--r--libk3b/projects/audiocd/k3baudiojob.cpp864
-rw-r--r--libk3b/projects/audiocd/k3baudiojob.h107
-rw-r--r--libk3b/projects/audiocd/k3baudiojobtempdata.cpp132
-rw-r--r--libk3b/projects/audiocd/k3baudiojobtempdata.h64
-rw-r--r--libk3b/projects/audiocd/k3baudiomaxspeedjob.cpp224
-rw-r--r--libk3b/projects/audiocd/k3baudiomaxspeedjob.h43
-rw-r--r--libk3b/projects/audiocd/k3baudionormalizejob.cpp205
-rw-r--r--libk3b/projects/audiocd/k3baudionormalizejob.h63
-rw-r--r--libk3b/projects/audiocd/k3baudiotrack.cpp628
-rw-r--r--libk3b/projects/audiocd/k3baudiotrack.h214
-rw-r--r--libk3b/projects/audiocd/k3baudiozerodata.cpp115
-rw-r--r--libk3b/projects/audiocd/k3baudiozerodata.h55
-rw-r--r--libk3b/projects/datacd/Makefile.am35
-rw-r--r--libk3b/projects/datacd/k3bbootitem.cpp58
-rw-r--r--libk3b/projects/datacd/k3bbootitem.h66
-rw-r--r--libk3b/projects/datacd/k3bdatadoc.cpp1376
-rw-r--r--libk3b/projects/datacd/k3bdatadoc.h297
-rw-r--r--libk3b/projects/datacd/k3bdataitem.cpp264
-rw-r--r--libk3b/projects/datacd/k3bdataitem.h225
-rw-r--r--libk3b/projects/datacd/k3bdatajob.cpp972
-rw-r--r--libk3b/projects/datacd/k3bdatajob.h111
-rw-r--r--libk3b/projects/datacd/k3bdatapreparationjob.cpp283
-rw-r--r--libk3b/projects/datacd/k3bdatapreparationjob.h51
-rw-r--r--libk3b/projects/datacd/k3bdiritem.cpp406
-rw-r--r--libk3b/projects/datacd/k3bdiritem.h155
-rw-r--r--libk3b/projects/datacd/k3bfilecompilationsizehandler.cpp228
-rw-r--r--libk3b/projects/datacd/k3bfilecompilationsizehandler.h73
-rw-r--r--libk3b/projects/datacd/k3bfileitem.cpp300
-rw-r--r--libk3b/projects/datacd/k3bfileitem.h124
-rw-r--r--libk3b/projects/datacd/k3bisoimager.cpp1187
-rw-r--r--libk3b/projects/datacd/k3bisoimager.h188
-rw-r--r--libk3b/projects/datacd/k3bisooptions.cpp216
-rw-r--r--libk3b/projects/datacd/k3bisooptions.h183
-rw-r--r--libk3b/projects/datacd/k3bmkisofshandler.cpp150
-rw-r--r--libk3b/projects/datacd/k3bmkisofshandler.h74
-rw-r--r--libk3b/projects/datacd/k3bmsinfofetcher.cpp243
-rw-r--r--libk3b/projects/datacd/k3bmsinfofetcher.h64
-rw-r--r--libk3b/projects/datacd/k3bsessionimportitem.cpp59
-rw-r--r--libk3b/projects/datacd/k3bsessionimportitem.h63
-rw-r--r--libk3b/projects/datacd/k3bspecialdataitem.h76
-rw-r--r--libk3b/projects/datadvd/Makefile.am21
-rw-r--r--libk3b/projects/datadvd/k3bdvdbooktypejob.cpp350
-rw-r--r--libk3b/projects/datadvd/k3bdvdbooktypejob.h99
-rw-r--r--libk3b/projects/datadvd/k3bdvddoc.cpp39
-rw-r--r--libk3b/projects/datadvd/k3bdvddoc.h37
-rw-r--r--libk3b/projects/datadvd/k3bdvdjob.cpp344
-rw-r--r--libk3b/projects/datadvd/k3bdvdjob.h57
-rw-r--r--libk3b/projects/datadvd/k3bdvdview.cpp48
-rw-r--r--libk3b/projects/datadvd/k3bdvdview.h40
-rw-r--r--libk3b/projects/k3babstractwriter.cpp96
-rw-r--r--libk3b/projects/k3babstractwriter.h92
-rw-r--r--libk3b/projects/k3bcdrdaowriter.cpp1101
-rw-r--r--libk3b/projects/k3bcdrdaowriter.h157
-rw-r--r--libk3b/projects/k3bcdrecordwriter.cpp810
-rw-r--r--libk3b/projects/k3bcdrecordwriter.h123
-rw-r--r--libk3b/projects/k3bcuefileparser.cpp461
-rw-r--r--libk3b/projects/k3bcuefileparser.h57
-rw-r--r--libk3b/projects/k3bdoc.cpp221
-rw-r--r--libk3b/projects/k3bdoc.h229
-rw-r--r--libk3b/projects/k3bdvdrecordwriter.cpp119
-rw-r--r--libk3b/projects/k3bdvdrecordwriter.h40
-rw-r--r--libk3b/projects/k3bgrowisofshandler.cpp318
-rw-r--r--libk3b/projects/k3bgrowisofshandler.h87
-rw-r--r--libk3b/projects/k3bgrowisofswriter.cpp630
-rw-r--r--libk3b/projects/k3bgrowisofswriter.h106
-rw-r--r--libk3b/projects/k3bimagefilereader.cpp88
-rw-r--r--libk3b/projects/k3bimagefilereader.h55
-rw-r--r--libk3b/projects/k3binffilewriter.cpp186
-rw-r--r--libk3b/projects/k3binffilewriter.h119
-rw-r--r--libk3b/projects/k3bpipebuffer.cpp281
-rw-r--r--libk3b/projects/k3bpipebuffer.h59
-rw-r--r--libk3b/projects/k3btocfilewriter.cpp356
-rw-r--r--libk3b/projects/k3btocfilewriter.h62
-rw-r--r--libk3b/projects/mixedcd/Makefile.am23
-rw-r--r--libk3b/projects/mixedcd/k3bmixeddoc.cpp249
-rw-r--r--libk3b/projects/mixedcd/k3bmixeddoc.h95
-rw-r--r--libk3b/projects/mixedcd/k3bmixedjob.cpp1339
-rw-r--r--libk3b/projects/mixedcd/k3bmixedjob.h144
-rw-r--r--libk3b/projects/movixcd/Makefile.am23
-rw-r--r--libk3b/projects/movixcd/k3bmovixdoc.cpp445
-rw-r--r--libk3b/projects/movixcd/k3bmovixdoc.h125
-rw-r--r--libk3b/projects/movixcd/k3bmovixdocpreparer.cpp490
-rw-r--r--libk3b/projects/movixcd/k3bmovixdocpreparer.h67
-rw-r--r--libk3b/projects/movixcd/k3bmovixfileitem.cpp68
-rw-r--r--libk3b/projects/movixcd/k3bmovixfileitem.h52
-rw-r--r--libk3b/projects/movixcd/k3bmovixjob.cpp132
-rw-r--r--libk3b/projects/movixcd/k3bmovixjob.h60
-rw-r--r--libk3b/projects/movixcd/k3bmovixprogram.cpp339
-rw-r--r--libk3b/projects/movixcd/k3bmovixprogram.h103
-rw-r--r--libk3b/projects/movixdvd/Makefile.am21
-rw-r--r--libk3b/projects/movixdvd/k3bmovixdvddoc.cpp36
-rw-r--r--libk3b/projects/movixdvd/k3bmovixdvddoc.h40
-rw-r--r--libk3b/projects/movixdvd/k3bmovixdvdjob.cpp131
-rw-r--r--libk3b/projects/movixdvd/k3bmovixdvdjob.h60
-rw-r--r--libk3b/projects/videocd/Makefile.am20
-rw-r--r--libk3b/projects/videocd/cdi/Makefile.am5
-rw-r--r--libk3b/projects/videocd/cdi/cdi_imag.rtfbin0 -> 1314877 bytes
-rw-r--r--libk3b/projects/videocd/cdi/cdi_text.fntbin0 -> 13616 bytes
-rw-r--r--libk3b/projects/videocd/cdi/cdi_vcd.appbin0 -> 102400 bytes
-rw-r--r--libk3b/projects/videocd/cdi/cdi_vcd.cfg12
-rw-r--r--libk3b/projects/videocd/cdi/icdia.htm12
-rw-r--r--libk3b/projects/videocd/cdi/vcd_on_cdi_41.pdfbin0 -> 126675 bytes
-rw-r--r--libk3b/projects/videocd/extra/Makefile.am5
-rw-r--r--libk3b/projects/videocd/extra/k3bphotosvcd.mpgbin0 -> 824970 bytes
-rw-r--r--libk3b/projects/videocd/extra/k3bphotovcd.mpgbin0 -> 1731138 bytes
-rw-r--r--libk3b/projects/videocd/k3bvcddoc.cpp894
-rw-r--r--libk3b/projects/videocd/k3bvcddoc.h192
-rw-r--r--libk3b/projects/videocd/k3bvcdjob.cpp567
-rw-r--r--libk3b/projects/videocd/k3bvcdjob.h115
-rw-r--r--libk3b/projects/videocd/k3bvcdoptions.cpp146
-rw-r--r--libk3b/projects/videocd/k3bvcdoptions.h377
-rw-r--r--libk3b/projects/videocd/k3bvcdtrack.cpp456
-rw-r--r--libk3b/projects/videocd/k3bvcdtrack.h198
-rw-r--r--libk3b/projects/videocd/k3bvcdxmlview.cpp440
-rw-r--r--libk3b/projects/videocd/k3bvcdxmlview.h59
-rw-r--r--libk3b/projects/videocd/mpeginfo/Makefile.am5
-rw-r--r--libk3b/projects/videocd/mpeginfo/k3bmpeginfo.cpp844
-rw-r--r--libk3b/projects/videocd/mpeginfo/k3bmpeginfo.h178
-rw-r--r--libk3b/projects/videodvd/Makefile.am20
-rw-r--r--libk3b/projects/videodvd/k3bvideodvddoc.cpp71
-rw-r--r--libk3b/projects/videodvd/k3bvideodvddoc.h46
-rw-r--r--libk3b/projects/videodvd/k3bvideodvdimager.cpp221
-rw-r--r--libk3b/projects/videodvd/k3bvideodvdimager.h61
-rw-r--r--libk3b/projects/videodvd/k3bvideodvdjob.cpp101
-rw-r--r--libk3b/projects/videodvd/k3bvideodvdjob.h46
-rw-r--r--libk3b/scripts/Makefile.am11
-rwxr-xr-xlibk3b/scripts/k3b_automount66
-rw-r--r--libk3b/tools/Makefile.am44
-rw-r--r--libk3b/tools/k3bactivepipe.cpp255
-rw-r--r--libk3b/tools/k3bactivepipe.h134
-rw-r--r--libk3b/tools/k3bbusywidget.cpp103
-rw-r--r--libk3b/tools/k3bbusywidget.h54
-rw-r--r--libk3b/tools/k3bcdparanoialib.cpp783
-rw-r--r--libk3b/tools/k3bcdparanoialib.h161
-rw-r--r--libk3b/tools/k3bcdtextvalidator.cpp42
-rw-r--r--libk3b/tools/k3bcdtextvalidator.h33
-rw-r--r--libk3b/tools/k3bchecksumpipe.cpp99
-rw-r--r--libk3b/tools/k3bchecksumpipe.h66
-rw-r--r--libk3b/tools/k3bcutcombobox.cpp230
-rw-r--r--libk3b/tools/k3bcutcombobox.h92
-rw-r--r--libk3b/tools/k3bdevicecombobox.cpp174
-rw-r--r--libk3b/tools/k3bdevicecombobox.h67
-rw-r--r--libk3b/tools/k3bdevicehandler.cpp332
-rw-r--r--libk3b/tools/k3bdevicehandler.h237
-rw-r--r--libk3b/tools/k3bdeviceselectiondialog.cpp130
-rw-r--r--libk3b/tools/k3bdeviceselectiondialog.h62
-rw-r--r--libk3b/tools/k3bdirsizejob.cpp184
-rw-r--r--libk3b/tools/k3bdirsizejob.h67
-rw-r--r--libk3b/tools/k3bexceptions.cpp43
-rw-r--r--libk3b/tools/k3bexceptions.h35
-rw-r--r--libk3b/tools/k3bfilesplitter.cpp307
-rw-r--r--libk3b/tools/k3bfilesplitter.h108
-rw-r--r--libk3b/tools/k3bfilesysteminfo.cpp141
-rw-r--r--libk3b/tools/k3bfilesysteminfo.h56
-rw-r--r--libk3b/tools/k3bintmapcombobox.cpp127
-rw-r--r--libk3b/tools/k3bintmapcombobox.h83
-rw-r--r--libk3b/tools/k3bintvalidator.cpp137
-rw-r--r--libk3b/tools/k3bintvalidator.h84
-rw-r--r--libk3b/tools/k3biso9660.cpp899
-rw-r--r--libk3b/tools/k3biso9660.h453
-rw-r--r--libk3b/tools/k3biso9660backend.cpp239
-rw-r--r--libk3b/tools/k3biso9660backend.h95
-rw-r--r--libk3b/tools/k3blibdvdcss.cpp307
-rw-r--r--libk3b/tools/k3blibdvdcss.h84
-rw-r--r--libk3b/tools/k3blistview.cpp1290
-rw-r--r--libk3b/tools/k3blistview.h296
-rw-r--r--libk3b/tools/k3blistviewitemanimator.cpp137
-rw-r--r--libk3b/tools/k3blistviewitemanimator.h78
-rw-r--r--libk3b/tools/k3bmd5job.cpp322
-rw-r--r--libk3b/tools/k3bmd5job.h92
-rw-r--r--libk3b/tools/k3bmsfedit.cpp153
-rw-r--r--libk3b/tools/k3bmsfedit.h70
-rw-r--r--libk3b/tools/k3bmultichoicedialog.cpp191
-rw-r--r--libk3b/tools/k3bmultichoicedialog.h73
-rw-r--r--libk3b/tools/k3bpipe.cpp79
-rw-r--r--libk3b/tools/k3bpipe.h60
-rw-r--r--libk3b/tools/k3bprogressdialog.cpp107
-rw-r--r--libk3b/tools/k3bprogressdialog.h63
-rw-r--r--libk3b/tools/k3bpushbutton.cpp136
-rw-r--r--libk3b/tools/k3bpushbutton.h75
-rw-r--r--libk3b/tools/k3bradioaction.cpp94
-rw-r--r--libk3b/tools/k3bradioaction.h122
-rw-r--r--libk3b/tools/k3brichtextlabel.cpp109
-rw-r--r--libk3b/tools/k3brichtextlabel.h62
-rw-r--r--libk3b/tools/k3bsignalwaiter.cpp62
-rw-r--r--libk3b/tools/k3bsignalwaiter.h51
-rw-r--r--libk3b/tools/k3bstdguiitems.cpp215
-rw-r--r--libk3b/tools/k3bstdguiitems.h45
-rw-r--r--libk3b/tools/k3bstringutils.cpp111
-rw-r--r--libk3b/tools/k3bstringutils.h39
-rw-r--r--libk3b/tools/k3btempfile.cpp51
-rw-r--r--libk3b/tools/k3btempfile.h43
-rw-r--r--libk3b/tools/k3bthreadwidget.cpp142
-rw-r--r--libk3b/tools/k3bthreadwidget.h78
-rw-r--r--libk3b/tools/k3bthroughputestimator.cpp98
-rw-r--r--libk3b/tools/k3bthroughputestimator.h57
-rw-r--r--libk3b/tools/k3btitlelabel.cpp266
-rw-r--r--libk3b/tools/k3btitlelabel.h68
-rw-r--r--libk3b/tools/k3btoolbox.cpp293
-rw-r--r--libk3b/tools/k3btoolbox.h93
-rw-r--r--libk3b/tools/k3btoolbutton.cpp109
-rw-r--r--libk3b/tools/k3btoolbutton.h50
-rw-r--r--libk3b/tools/k3bvalidators.cpp154
-rw-r--r--libk3b/tools/k3bvalidators.h131
-rw-r--r--libk3b/tools/k3bwavefilewriter.cpp186
-rw-r--r--libk3b/tools/k3bwavefilewriter.h78
-rw-r--r--libk3b/tools/kcutlabel.cpp115
-rw-r--r--libk3b/tools/kcutlabel.h68
-rw-r--r--libk3b/tools/libisofs/COPYING280
-rw-r--r--libk3b/tools/libisofs/ChangeLog9
-rw-r--r--libk3b/tools/libisofs/Makefile.am5
-rw-r--r--libk3b/tools/libisofs/README24
-rw-r--r--libk3b/tools/libisofs/bswap.h94
-rw-r--r--libk3b/tools/libisofs/el_torito.h63
-rw-r--r--libk3b/tools/libisofs/iso_fs.h219
-rw-r--r--libk3b/tools/libisofs/isofs.cpp878
-rw-r--r--libk3b/tools/libisofs/isofs.h151
-rw-r--r--libk3b/tools/libisofs/rock.h127
-rw-r--r--libk3b/videodvd/Makefile.am19
-rw-r--r--libk3b/videodvd/configure.in.bot11
-rw-r--r--libk3b/videodvd/configure.in.in28
-rw-r--r--libk3b/videodvd/k3bvideodvd.cpp327
-rw-r--r--libk3b/videodvd/k3bvideodvd.h91
-rw-r--r--libk3b/videodvd/k3bvideodvdaudiostream.h112
-rw-r--r--libk3b/videodvd/k3bvideodvdptt.h50
-rw-r--r--libk3b/videodvd/k3bvideodvdsubpicturestream.h68
-rw-r--r--libk3b/videodvd/k3bvideodvdtime.cpp106
-rw-r--r--libk3b/videodvd/k3bvideodvdtime.h59
-rw-r--r--libk3b/videodvd/k3bvideodvdtitle.h112
-rw-r--r--libk3b/videodvd/k3bvideodvdvideostream.cpp60
-rw-r--r--libk3b/videodvd/k3bvideodvdvideostream.h107
362 files changed, 91051 insertions, 0 deletions
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 <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 <qstring.h>
+#include <qvaluelist.h>
+#include <qstringlist.h>
+#include <qtimer.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+
+#include "k3bcddb.h"
+#include "k3bcddbhttpquery.h"
+#include "k3bcddbpquery.h"
+#include "k3bcddblocalquery.h"
+#include "k3bcddblocalsubmit.h"
+
+#include <k3btoc.h>
+#include <k3btrack.h>
+#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 <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 K3BCDDB_H
+#define K3BCDDB_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qobject.h>
+
+#include <k3btoc.h>
+
+#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 <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 "k3bcddbhttpquery.h"
+
+#include "k3bcddbresult.h"
+
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kio/global.h>
+#include <kio/job.h>
+
+
+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 <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 K3BCDDB_HTTP_QUERY_H
+#define K3BCDDB_HTTP_QUERY_H
+
+#include "k3bcddbquery.h"
+#include "k3bcddbresult.h"
+
+#include <qvaluelist.h>
+
+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 <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 "k3bcddblocalquery.h"
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qtextstream.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+
+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 <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 K3BCDDB_LOCAL_QUERY_H
+#define K3BCDDB_LOCAL_QUERY_H
+
+#include "k3bcddbquery.h"
+#include "k3bcddbresult.h"
+
+#include <qstring.h>
+
+
+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 <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 "k3bcddblocalsubmit.h"
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qtextstream.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+
+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 <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 K3BCDDB_LOCAL_SUBMIT_H
+#define K3BCDDB_LOCAL_SUBMIT_H
+
+#include "k3bcddbsubmit.h"
+
+#include <qstring.h>
+
+
+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 <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 "k3bcddbmultientriesdialog.h"
+
+#include <qlayout.h>
+#include <qframe.h>
+#include <qlabel.h>
+
+#include <klistbox.h>
+#include <klocale.h>
+
+
+
+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<K3bCddbResultHeader> headers = query->getInexactMatches();
+
+ int i = 1;
+ for( QValueListConstIterator<K3bCddbResultHeader> 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 <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 K3BCDDBMULTIENTRIESDIALOG_H
+#define K3BCDDBMULTIENTRIESDIALOG_H
+
+#include <kdialogbase.h>
+
+#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 <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 "k3bcddbpquery.h"
+
+#include <qstringlist.h>
+#include <qsocket.h>
+#include <qtextstream.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+
+
+
+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 <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 K3BCDDBP_QUERY_H
+#define K3BCDDBP_QUERY_H
+
+#include "k3bcddbquery.h"
+#include "k3bcddbresult.h"
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qtextstream.h>
+
+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 <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 "k3bcddbquery.h"
+
+#include "k3bcddbresult.h"
+
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+
+
+#include <qtextstream.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <qtimer.h>
+
+#include <stdlib.h>
+
+
+
+
+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 <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 K3BCDDB_QUERY_H
+#define K3BCDDB_QUERY_H
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qtextstream.h>
+
+#include "k3bcddbresult.h"
+
+#include <k3btoc.h>
+#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<K3bCddbResultHeader>& 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<K3bCddbResultHeader> 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 <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 "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 <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_CDDB_RESULT_H
+#define K3B_CDDB_RESULT_H
+
+
+#include <qstringlist.h>
+#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<K3bCddbResultEntry> 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 <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 "k3bcddbsubmit.h"
+
+#include <qtimer.h>
+
+
+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 <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 K3BCDDB_SUBMIT_H
+#define K3BCDDB_SUBMIT_H
+
+#include <qobject.h>
+#include <qstring.h>
+
+#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 <montel@kde.org>
+ * Copyright (C) 2005-2007 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_EXPORT_H_
+#define _K3B_EXPORT_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#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 <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 <config.h>
+
+#include "k3bcore.h"
+#include "k3bjob.h"
+
+#include <k3bdevicemanager.h>
+#ifdef HAVE_HAL
+#include <k3bhalconnection.h>
+#endif
+#include <k3bexternalbinmanager.h>
+#include <k3bdefaultexternalprograms.h>
+#include <k3bglobals.h>
+#include <k3bversion.h>
+#include <k3bjob.h>
+#include <k3bthreadwidget.h>
+#include <k3bglobalsettings.h>
+#include <k3bpluginmanager.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kaboutdata.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+
+#include <qptrlist.h>
+#include <qthread.h>
+#include <qmutex.h>
+
+
+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<K3bJob*> runningJobs;
+ QValueList<K3bDevice::Device*> 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<K3bCore*>(this)->initDeviceManager();
+ return d->deviceManager;
+}
+
+
+K3bExternalBinManager* K3bCore::externalBinManager() const
+{
+ const_cast<K3bCore*>(this)->initExternalBinManager();
+ return d->externalBinManager;
+}
+
+
+K3bPluginManager* K3bCore::pluginManager() const
+{
+ const_cast<K3bCore*>(this)->initPluginManager();
+ return d->pluginManager;
+}
+
+
+K3bGlobalSettings* K3bCore::globalSettings() const
+{
+ const_cast<K3bCore*>(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<K3bBurnJob*>( job ) )
+ emit burnJobStarted( bj );
+}
+
+
+void K3bCore::unregisterJob( K3bJob* job )
+{
+ d->runningJobs.remove( job );
+ emit jobFinished( job );
+ if( K3bBurnJob* bj = dynamic_cast<K3bBurnJob*>( job ) )
+ emit burnJobFinished( bj );
+}
+
+
+bool K3bCore::jobsRunning() const
+{
+ return !d->runningJobs.isEmpty();
+}
+
+
+const QValueList<K3bJob*>& 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<DeviceBlockingEvent*>(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 <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_CORE_H_
+#define _K3B_CORE_H_
+
+#include <qobject.h>
+#include <qvaluelist.h>
+
+#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<K3bJob*>& 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:
+ * <pre>externalBinManager()->addProgram( new K3bNormalizeProgram() );</pre>
+ */
+ 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 <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_DATA_EVENT_H
+#define K3B_DATA_EVENT_H
+
+#include <qevent.h>
+
+
+/**
+ * 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 <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 "k3bdefaultexternalprograms.h"
+#include "k3bexternalbinmanager.h"
+#include <k3bglobals.h>
+
+#include <qfile.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qobject.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include <k3bprocess.h>
+#include <kdebug.h>
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+
+
+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 <appro@fy.chalmers.se>";
+
+ // 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 <appro@fy.chalmers.se>";
+
+ // 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 <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_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 <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 "k3bexternalbinmanager.h"
+
+#include <kdebug.h>
+#include <kprocess.h>
+#include <kconfig.h>
+#include <kdeversion.h>
+
+#include <qstring.h>
+#include <qregexp.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qptrlist.h>
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+
+
+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<K3bExternalBin> 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<K3bExternalBin> 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<QString, K3bExternalProgram*>::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<QString, K3bExternalProgram*>::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<QString, K3bExternalProgram*>::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<QString, K3bExternalProgram*>::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<QString, K3bExternalProgram*>::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 <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_EXTERNAL_BIN_MANAGER_H
+#define K3B_EXTERNAL_BIN_MANAGER_H
+
+#include <qmap.h>
+#include <qobject.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qptrlist.h>
+#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<K3bExternalBin>& 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<K3bExternalBin> 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<QString, K3bExternalProgram*>& 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<QString, K3bExternalProgram*> 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 <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 <config.h>
+
+
+#include "k3bglobals.h"
+#include <k3bversion.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bdeviceglobals.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bcore.h>
+#include <k3bhalconnection.h>
+
+#include <kdeversion.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <kurl.h>
+#include <dcopref.h>
+#include <kprocess.h>
+
+#include <qdatastream.h>
+#include <qdir.h>
+#include <qfile.h>
+
+#include <cmath>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+# include <sys/param.h>
+# include <sys/mount.h>
+# include <sys/endian.h>
+# define bswap_16(x) bswap16(x)
+# define bswap_32(x) bswap32(x)
+# define bswap_64(x) bswap64(x)
+#else
+# include <byteswap.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h>
+#endif
+#ifdef HAVE_SYS_VFS_H
+# include <sys/vfs.h>
+#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 <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 K3BGLOBALS_H
+#define K3BGLOBALS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qfile.h>
+#include <kio/global.h>
+#include <kurl.h>
+#include <k3bdevicetypes.h>
+#include "k3b_export.h"
+
+class KConfig;
+class K3bVersion;
+class K3bExternalBin;
+
+
+#include <sys/stat.h>
+
+
+#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 <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 "k3bglobalsettings.h"
+
+#include <kconfig.h>
+
+
+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 <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_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 <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 "k3bjob.h"
+#include <k3bglobals.h>
+#include <k3bcore.h>
+
+#include <klocale.h>
+#include <kprocess.h>
+
+#include <qstringlist.h>
+#include <kdebug.h>
+
+
+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<K3bJob*>(jobHandler())->registerSubJob( this );
+ else
+ k3bcore->registerJob( this );
+
+ emit started();
+}
+
+
+void K3bJob::jobFinished( bool success )
+{
+ m_active = false;
+
+ if( jobHandler() && jobHandler()->isJob() )
+ static_cast<K3bJob*>(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 <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 K3BJOB_H
+#define K3BJOB_H
+
+#include <qobject.h>
+#include <qptrlist.h>
+#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<K3bJob>& 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<K3bJob> 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 <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_JOB_HANDLER_H_
+#define _K3B_JOB_HANDLER_H_
+
+
+#include <k3bdiskinfo.h>
+#include <k3bdevice.h>
+
+
+/**
+ * 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 <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 "k3bprocess.h"
+#include "k3bexternalbinmanager.h"
+
+#include <qstringlist.h>
+#include <qsocketnotifier.h>
+#include <qptrqueue.h>
+#include <qapplication.h>
+
+#include <kdebug.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+
+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<KProcess*>(this)->operator<<( arg );
+ return *this;
+}
+
+K3bProcess& K3bProcess::operator<<( const char* arg )
+{
+ static_cast<KProcess*>(this)->operator<<( arg );
+ return *this;
+}
+
+K3bProcess& K3bProcess::operator<<( const QCString& arg )
+{
+ static_cast<KProcess*>(this)->operator<<( arg );
+ return *this;
+}
+
+K3bProcess& K3bProcess::operator<<( const QStringList& args )
+{
+ static_cast<KProcess*>(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 <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_PROCESS_H
+#define K3B_PROCESS_H
+
+
+#include <kprocess.h>
+#include <qstring.h>
+#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 <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_PROGRESS_INFO_EVENT_H
+#define K3B_PROGRESS_INFO_EVENT_H
+
+#include <qevent.h>
+#include <qstring.h>
+
+
+/**
+ * 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 <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 "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 <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_SIMPLE_JOB_HANDLER_H_
+#define _K3B_SIMPLE_JOB_HANDLER_H_
+
+#include <k3b_export.h>
+
+#include <qobject.h>
+#include <k3bjobhandler.h>
+
+
+/**
+ * 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 <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 "k3bthread.h"
+#include "k3bprogressinfoevent.h"
+#include "k3bdataevent.h"
+
+#include <kdebug.h>
+
+#include <qapplication.h>
+
+
+static QPtrList<K3bThread> s_threads;
+
+
+void K3bThread::waitUntilFinished()
+{
+ QPtrListIterator<K3bThread> 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 <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_THREAD_H_
+#define _K3B_THREAD_H_
+
+#include <qthread.h>
+#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 <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 "k3bthreadjob.h"
+#include "k3bthread.h"
+#include "k3bprogressinfoevent.h"
+#include "k3bdataevent.h"
+
+#include <kdebug.h>
+#include <kapplication.h>
+
+
+
+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<K3bDataEvent*>(e) ) {
+ emit data( de->data(), de->length() );
+ }
+ else {
+ K3bProgressInfoEvent* be = static_cast<K3bProgressInfoEvent*>(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 <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_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:
+ * <pre>
+ * K3bThread* thread = new MySuperThread(...);
+ * K3bThreadJob* job = new K3bThreadJob( thread, ... );
+ * K3bBurnProgressDialog d;
+ * d.setJob(job);
+ * job->start();
+ * d.exec();
+ * delete job;
+ * </pre>
+ * 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 <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 "k3bversion.h"
+
+#include <qregexp.h>
+#include <kdebug.h>
+
+
+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 <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_VERSION_H_
+#define _K3B_VERSION_H_
+
+#include <qstring.h>
+#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 <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 "k3baudiocuefilewritingjob.h"
+
+#include <k3baudiodoc.h>
+#include <k3baudiojob.h>
+#include <k3bdevice.h>
+#include <k3baudiodecoder.h>
+#include <k3baudiotrack.h>
+#include <k3baudiofile.h>
+#include <k3bcuefileparser.h>
+#include <k3bthread.h>
+#include <k3bthreadjob.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+
+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 <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_AUDIO_CUE_FILEWRITING_JOB_H_
+#define _K3B_AUDIO_CUE_FILEWRITING_JOB_H_
+
+#include <k3bjob.h>
+#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 <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 "k3baudiosessionreadingjob.h"
+
+#include <k3bthread.h>
+#include <k3btoc.h>
+#include <k3bcdparanoialib.h>
+#include <k3bwavefilewriter.h>
+#include <k3bglobals.h>
+#include <k3bdevice.h>
+#include <k3bcore.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <unistd.h>
+
+
+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 <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_AUDIOSESSION_READING_JOB_H_
+#define _K3B_AUDIOSESSION_READING_JOB_H_
+
+#include <k3bthreadjob.h>
+
+#include <qstringlist.h>
+
+
+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 <kd@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 "k3bbinimagewritingjob.h"
+#include <k3bcdrecordwriter.h>
+#include <k3bcdrdaowriter.h>
+#include <k3bcore.h>
+#include <k3bdevice.h>
+#include <k3bglobals.h>
+#include <k3bexternalbinmanager.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qfile.h>
+#include <qtextstream.h>
+
+
+
+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 <kd@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 K3BBINIMAGEWRITINGJOB_H
+#define K3BBINIMAGEWRITINGJOB_H
+
+#include <k3bjob.h>
+#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 <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 "k3bblankingjob.h"
+#include "k3bcdrecordwriter.h"
+#include "k3bcdrdaowriter.h"
+
+#include <k3bglobals.h>
+#include <k3bdevice.h>
+#include <k3bdevicehandler.h>
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <kio/global.h>
+#include <kio/job.h>
+#include <kdebug.h>
+
+#include <qstring.h>
+
+
+
+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<p><b>%1 %2 (%3)</b>.")
+ .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 <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_BLANKING_JOB_H
+#define K3B_BLANKING_JOB_H
+
+#include <k3bjob.h>
+#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 <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 "k3bcdcopyjob.h"
+#include "k3baudiosessionreadingjob.h"
+
+#include <k3bexternalbinmanager.h>
+#include <k3bdevice.h>
+#include <k3bdiskinfo.h>
+#include <k3btoc.h>
+#include <k3bglobals.h>
+#include <k3bdevicehandler.h>
+#include <k3breadcdreader.h>
+#include <k3bdatatrackreader.h>
+#include <k3bcdrecordwriter.h>
+#include <k3bcdtext.h>
+#include <k3bcddb.h>
+#include <k3bcddbresult.h>
+#include <k3bcddbquery.h>
+#include <k3bcore.h>
+#include <k3binffilewriter.h>
+
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <ktempfile.h>
+#include <kio/netaccess.h>
+#include <kio/job.h>
+#include <kio/global.h>
+
+#include <qtimer.h>
+#include <qstringlist.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+#include <qcstring.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qapplication.h>
+
+
+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<bool> dataSessionProbablyTAORecorded;
+
+ // used to determine progress
+ QValueVector<long> 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 <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 _K3BCDCOPYJOB_H_
+#define _K3BCDCOPYJOB_H_
+
+#include <k3bjob.h>
+#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 <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 "k3bcdda2wavreader.h"
+
+#include <k3bexternalbinmanager.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bcore.h>
+#include <k3bprocess.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qvaluevector.h>
+#include <qregexp.h>
+
+
+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<int> 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 <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_CDDA2WAV_READER_H_
+#define _K3B_CDDA2WAV_READER_H_
+
+#include <k3bjob.h>
+
+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 <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 "k3bclonejob.h"
+
+#include <k3breadcdreader.h>
+#include <k3bcdrecordwriter.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bdevice.h>
+#include <k3bdevicehandler.h>
+#include <k3bglobals.h>
+#include <k3bcore.h>
+#include <k3bclonetocreader.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+
+
+
+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 <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_CLONE_JOB_H_
+#define _K3B_CLONE_JOB_H_
+
+#include <k3bjob.h>
+#include "k3b_export.h"
+#include <qstring.h>
+
+
+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 <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 <config.h>
+
+
+#include "k3bclonetocreader.h"
+
+#include <k3bdeviceglobals.h>
+#include <k3bglobals.h>
+
+#include <qfile.h>
+#include <qtextstream.h>
+
+#include <kdebug.h>
+
+
+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 <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_CLONETOC_FILE_PARSER_H_
+#define _K3B_CLONETOC_FILE_PARSER_H_
+
+#include "k3bimagefilereader.h"
+
+#include <k3bmsf.h>
+
+#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 <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 "k3bdatatrackreader.h"
+
+#include <k3blibdvdcss.h>
+#include <k3bdevice.h>
+#include <k3bdeviceglobals.h>
+#include <k3btrack.h>
+#include <k3bthread.h>
+#include <k3bcore.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qfile.h>
+
+#include <unistd.h>
+
+
+
+// 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<void*>(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<char*>(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<void*>(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 <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_DATATRACK_READER_H_
+#define _K3B_DATATRACK_READER_H_
+
+
+#include <k3bthreadjob.h>
+#include <k3bmsf.h>
+#include <k3bglobals.h>
+
+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 <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 "k3bdvdcopyjob.h"
+#include "k3blibdvdcss.h"
+
+#include <k3breadcdreader.h>
+#include <k3bdatatrackreader.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bdevice.h>
+#include <k3bdeviceglobals.h>
+#include <k3bdevicehandler.h>
+#include <k3bdiskinfo.h>
+#include <k3bglobals.h>
+#include <k3bcore.h>
+#include <k3bgrowisofswriter.h>
+#include <k3bversion.h>
+#include <k3biso9660.h>
+#include <k3bfilesplitter.h>
+#include <k3bchecksumpipe.h>
+#include <k3bverificationjob.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kio/global.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qapplication.h>
+
+
+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 <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_DVD_COPY_JOB_H_
+#define _K3B_DVD_COPY_JOB_H_
+
+#include <k3bjob.h>
+#include "k3b_export.h"
+#include <qstring.h>
+
+
+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 <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 "k3bdvdformattingjob.h"
+
+#include <k3bglobals.h>
+#include <k3bprocess.h>
+#include <k3bdevice.h>
+#include <k3bdeviceglobals.h>
+#include <k3bdevicehandler.h>
+#include <k3bdiskinfo.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bcore.h>
+#include <k3bversion.h>
+#include <k3bglobalsettings.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qvaluelist.h>
+#include <qregexp.h>
+
+#include <errno.h>
+#include <string.h>
+
+
+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<p><b>%1 %2 (%3)</b>.")
+ .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 <appro@fy.chalmers.se>, 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<QCString>& args = d->process->args();
+ QString s;
+ for( QValueList<QCString>::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 <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_DVD_FORMATTING_JOB_H_
+#define _K3B_DVD_FORMATTING_JOB_H_
+
+
+#include <k3bjob.h>
+#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 <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 "k3biso9660imagewritingjob.h"
+#include "k3bverificationjob.h"
+
+#include <k3bdevice.h>
+#include <k3bdiskinfo.h>
+#include <k3bdevicehandler.h>
+#include <k3bcdrecordwriter.h>
+#include <k3bcdrdaowriter.h>
+#include <k3bgrowisofswriter.h>
+#include <k3bglobals.h>
+#include <k3bcore.h>
+#include <k3bversion.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bchecksumpipe.h>
+#include <k3bfilesplitter.h>
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <ktempfile.h>
+#include <kio/global.h>
+
+#include <qstring.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qapplication.h>
+
+
+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 <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 K3BISO9660_IMAGE_WRITING_JOB_H
+#define K3BISO9660_IMAGE_WRITING_JOB_H
+
+#include <k3bjob.h>
+#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 <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 "k3breadcdreader.h"
+
+#include <k3bcore.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bprocess.h>
+#include <k3bmsf.h>
+#include <k3bglobals.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kconfig.h>
+
+#include <qregexp.h>
+#include <qvaluelist.h>
+#include <qstringlist.h>
+
+
+
+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<K3bExternalBin>& readcdBins = readcdProgram->bins();
+ for( QPtrListIterator<K3bExternalBin> 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<QCString>& args = d->process->args();
+ QString s;
+ for( QValueList<QCString>::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 <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_READCD_READER_H_
+#define _K3B_READCD_READER_H_
+
+#include <k3bjob.h>
+
+
+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 <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 "k3bverificationjob.h"
+
+#include <k3bdevice.h>
+#include <k3bdevicehandler.h>
+#include <k3bmd5job.h>
+#include <k3bglobals.h>
+#include <k3bdatatrackreader.h>
+#include <k3bpipe.h>
+#include <k3biso9660.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kio/global.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+
+#include <qcstring.h>
+#include <qapplication.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+
+
+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<K3bVerificationJobTrackEntry> 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<K3bVerificationJobTrackEntry>::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 <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_VERIFICATION_JOB_H_
+#define _K3B_VERIFICATION_JOB_H_
+
+#include <k3bjob.h>
+
+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 <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 "k3bvideodvdtitledetectclippingjob.h"
+
+#include <k3bexternalbinmanager.h>
+#include <k3bprocess.h>
+#include <k3bcore.h>
+#include <k3bglobals.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+
+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<QCString>& args = d->process->args();
+ QString s;
+ for( QValueList<QCString>::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 <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_DETECTCLIPPING_JOB_H_
+#define _K3B_VIDEODVD_TITLE_DETECTCLIPPING_JOB_H_
+
+#include <k3b_export.h>
+#include <k3bjob.h>
+#include <k3bvideodvd.h>
+
+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 <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 "k3bvideodvdtitletranscodingjob.h"
+
+#include <k3bexternalbinmanager.h>
+#include <k3bprocess.h>
+#include <k3bcore.h>
+#include <k3bglobals.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+
+
+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 <codec>,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<QCString>& args = d->process->args();
+ QString s;
+ for( QValueList<QCString>::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.")
+ + "<br>"
+ + 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.")
+ + "<br>"
+ + 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.")
+ + "<br>"
+ + 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.")
+ + "<br><em>"
+ + i18n("(Description taken from the Wikipedia article)")
+ + "</em>";
+ 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
+ + "<br>" + i18n("With this setting K3b will create a two-channel stereo "
+ "Dolby Digital audio stream.");
+ case AUDIO_CODEC_AC3_PASSTHROUGH:
+ return s_ac3General
+ + "<br>" + i18n("With this setting K3b will use the Dolby Digital audio stream "
+ "from the source DVD without changing it.")
+ + "<br>" + 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.")
+ + "<br>" + 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 <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_TRANSCODING_JOB_H_
+#define _K3B_VIDEODVD_TITLE_TRANSCODING_JOB_H_
+
+#include <k3b_export.h>
+#include <k3bjob.h>
+#include <k3bvideodvd.h>
+
+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 @@
+<!--
+ This document describes the layout of the toc.xml file in a K3b image archive.
+ A K3b image archive is a TAR archive with a simple layout as follows.
+
+ Every K3b image archive contains the toc.xml file as described in this document
+ which describes the layout of the CD or DVD saved in the K3b image archive.
+ Additionally the K3b image archive contains an arbitrary number of files which
+ contain the CD/DVD sector data. These files are referenced in the elements of
+ type "file".
+
+ The most simple K3b image archive may look as follows:
+ Archive
+ |- toc.xml
+ |- image.iso
+ and the toc.xml may look as follows:
+ <image>
+ <numsessions>1</numsessions>
+ <numtracks>1</numtracks>
+ <session number="1">
+ <numtracks>1</numtracks>
+ <track number="1" type="Data Mode1">
+ <data sectorsize="2048">
+ <file>image.iso</file>
+ </data>
+ </track>
+ </session>
+ </image>
+
+
+ We used tar as a backend because K3b image archives tend to get really big when it
+ comes to DVD images and ZIP does not support archives bigger than 2 GB.
+ Although tar supports files bigger than 2 GB (inside the archive) K3b splits every
+ track bigger than 1 GB into chunks of 1 GB to avoid any problems with big filesizes.
+-->
+
+
+<!-- FIXME: introduce a version field! -->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://www.k3b.org"
+ xmlns="http://www.k3b.org"
+ elementFormDefault="qualified">
+
+<!-- THE TYPES -->
+ <xs:simpleType name="tracktype">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="Audio" />
+ <xs:enumeration value="Data Mode1" />
+ <xs:enumeration value="Data Mode2" />
+ <xs:enumeration value="Data XA Form1" />
+ <xs:enumeration value="Data XA Form2" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="sector_size">
+ <xs:restriction base="xs:integer">
+ <xs:enumeration value="2048" /> <!-- Mode1/Mode2 Form1/DVD: plain user data -->
+ <xs:enumeration value="2056" /> <!-- Mode2 Form1: 2048 bytes user data + 8 bytes sub header FIXME: or does this include 4 bytes crc? -->
+ <xs:enumeration value="2324" /> <!-- Mode2 Form2: plain user data -->
+ <xs:enumeration value="2332" /> <!-- Mode2 Form2: 2324 bytes user data + 8 bytes sub header FIXME: or does this include 4 bytes crc? -->
+ <xs:enumeration value="2352" /> <!-- Audio: 16bit, stereo, 44100Hz, big endian -->
+ <xs:enumeration value="2448" /> <!-- Raw data -->
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="filecontents">
+ <xs:simpleContent>
+ <!-- Filename in the image archive. -->
+ <xs:extension base="xs:string">
+ <!-- The start_sector allows for multiple tracks including the CD-TEXT to be defined in one file. Default: 0 -->
+ <xs:attribute name="start_offset" type="xs:nonNegativeInteger" use="optional" />
+
+ <!-- The number of bytes to be used. Default: up to end of the file -->
+ <xs:attribute name="length" type="xs:positiveInteger" use="optional" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name="catalogname">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9]{13}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="isrcname">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z0-9]{5}[0-9]{7}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+
+
+<!-- THE IMAGE DEFINITION -->
+
+ <xs:element name="image">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- Number of session for convinience -->
+ <xs:element name="numsessions" type="xs:positiveInteger" />
+
+ <!-- Number of tracks for convinience -->
+ <xs:element name="numtracks" type="xs:positiveInteger" />
+
+ <!-- CD-TEXT is always stored in binary form -->
+ <xs:element name="cdtext" type="filecontents" minOccurs="0" />
+
+ <!-- The optional catalog name. -->
+ <xs:element name="catalog" type="catalogname" minOccurs="0" />
+
+ <!-- The tracks are splitted into sessions. In most cases there will only be one session. -->
+ <xs:element name="session" maxOccurs="99"> <!-- FIXME: what is the real max here? -->
+ <xs:complexType>
+ <xs:sequence>
+ <!-- Number of tracks in this session for convinience -->
+ <xs:element name="numtracks" type="xs:positiveInteger" />
+
+ <!-- And here come the tracks. -->
+ <xs:element name="track" maxOccurs="99">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- The data tag contains file elements specifying where to find the data for the track.
+ The data may span over multiple files but all need to have the same sector size. -->
+ <xs:element name="data" minOccurs="1" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="file" type="filecontents" />
+ </xs:sequence>
+ <xs:attribute name="sectorsize" type="sector_size" />
+ </xs:complexType>
+ </xs:element>
+
+ <!-- The index tag contains the start sector of the index relative to the start of the track. -->
+ <xs:element name="index" minOccurs="0" maxOccurs="100">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:nonNegativeInteger">
+ <xs:attribute name="number" type="xs:nonNegativeInteger" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Pre emphasis. -->
+ <xs:element name="preemp" type="xs:boolean" minOccurs="0" default="false" />
+
+ <!-- Copy permitted. -->
+ <xs:element name="copy" type="xs:boolean" minOccurs="0" default="true" />
+
+ <!-- SCMS enabled (alternating copy control bit). Only useful in combination with
+ copy=true. -->
+ <xs:element name="scms" type="xs:boolean" minOccurs="0" default="false" />
+
+ <xs:element name="isrc" type="isrcname" minOccurs="0" />
+ </xs:sequence>
+
+ <!-- The track number for convinience. -->
+ <xs:attribute name="number" type="xs:positiveInteger" />
+
+ <!-- Type of the track as defined above. -->
+ <xs:attribute name="type" type="tracktype" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+
+ <!-- The session number for convinience. There is one special case in which the first session's number may be
+ bigger than 1. It is used internally by K3b to indicate that the image contains a session to be appended
+ to a multisession CD or DVD. It cannot be used in another situation since the data does only fit for the
+ multisession CD or DVD it was created for. -->
+ <xs:attribute name="number" type="xs:positiveInteger" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema> \ 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 <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 "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 <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_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 <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 <config.h>
+
+#include <k3bcore.h>
+
+#include "k3baudiodecoder.h"
+#include "k3bpluginmanager.h"
+
+#include <kdebug.h>
+#include <kfilemetainfo.h>
+
+#include <qmap.h>
+
+#include <math.h>
+
+#ifdef HAVE_LIBSAMPLERATE
+#include <samplerate.h>
+#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<QString, QString> technicalInfoMap;
+ QMap<MetaDataField, QString> 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<float>( 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<float>(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<QString, QString>::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<K3bPlugin> fl = k3bcore->pluginManager()->plugins( "AudioDecoder" );
+
+ // first search for a single format decoder
+ for( QPtrListIterator<K3bPlugin> it( fl ); it.current(); ++it ) {
+ K3bAudioDecoderFactory* f = dynamic_cast<K3bAudioDecoderFactory*>( 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<K3bPlugin> it( fl ); it.current(); ++it ) {
+ K3bAudioDecoderFactory* f = dynamic_cast<K3bAudioDecoderFactory*>( 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 <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_AUDIO_DECODER_H_
+#define _K3B_AUDIO_DECODER_H_
+
+
+#include <k3bplugin.h>
+#include <k3bmsf.h>
+#include "k3b_export.h"
+#include <kurl.h>
+
+
+
+/**
+ * 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 <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 "k3baudioencoder.h"
+
+#include <qfile.h>
+
+#include <kdebug.h>
+
+
+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 <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_AUDIO_ENCODER_H_
+#define _K3B_AUDIO_ENCODER_H_
+
+#include <k3bplugin.h>
+
+#include <k3bmsf.h>
+#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 <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_AUDIO_OUTPUTPLUGIN_H_
+#define _K3B_AUDIO_OUTPUTPLUGIN_H_
+
+#include <k3bplugin.h>
+#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 <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 <k3bcore.h>
+#include <k3bthread.h>
+#include <k3bprogressinfoevent.h>
+#include "k3baudioserver.h"
+#include "k3baudioclient.h"
+#include "k3bpluginmanager.h"
+#include "k3baudiooutputplugin.h"
+
+#include <kdebug.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include <k3bthread.h>
+
+
+
+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<K3bPlugin> fl = k3bcore->pluginManager()->plugins( "AudioOutput" );
+
+ for( QPtrListIterator<K3bPlugin> it( fl ); it.current(); ++it ) {
+ K3bAudioOutputPlugin* f = dynamic_cast<K3bAudioOutputPlugin*>( 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<K3bProgressInfoEvent*>(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 <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_AUDIO_SERVER_H_
+#define _K3B_AUDIO_SERVER_H_
+
+#include <qobject.h>
+#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 <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 "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 <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_PLUGIN_H_
+#define _K3B_PLUGIN_H_
+
+#include <qobject.h>
+#include <kgenericfactory.h>
+#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 <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 "k3bpluginconfigwidget.h"
+#include "k3bpluginfactory.h"
+
+#include <k3bcore.h>
+
+#include <kinstance.h>
+#include <kdebug.h>
+
+
+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 <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_PLUGIN_CONFIG_WIDGET_H_
+#define _K3B_PLUGIN_CONFIG_WIDGET_H_
+
+#include <qwidget.h>
+#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 <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 "k3bpluginfactory.h"
+
+
+template <class T>
+KInstance* K3bPluginFactory<T>::s_instance = 0;
+
+
+template <class T>
+K3bPluginFactory<T>* K3bPluginFactory<T>::s_self = 0;
+
+
+template <class T>
+KInstance* K3bPluginFactory<T>::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 <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_PLUGIN_FACTORY_H_
+#define _K3B_PLUGIN_FACTORY_H_
+
+#include <klibloader.h>
+#include <kinstance.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+/**
+ * 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>( "k3bartsaudioserver" ) )
+ *
+ * See KGenericFactory for more information.
+ */
+template <class T>
+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<T> *s_self;
+};
+
+
+template <class T>
+KInstance* K3bPluginFactory<T>::s_instance = 0;
+
+
+template <class T>
+K3bPluginFactory<T>* K3bPluginFactory<T>::s_self = 0;
+
+
+template <class T>
+KInstance* K3bPluginFactory<T>::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 <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 "k3bpluginmanager.h"
+#include "k3bplugin.h"
+#include "k3bpluginconfigwidget.h"
+#include <k3bversion.h>
+
+#include <kdebug.h>
+#include <ksimpleconfig.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kdialogbase.h>
+#include <kmessagebox.h>
+#include <klibloader.h>
+
+#include <qptrlist.h>
+#include <qmap.h>
+#include <qdir.h>
+
+
+
+class K3bPluginManager::Private
+{
+public:
+ QPtrList<K3bPlugin> 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<K3bPlugin> fl;
+ for( QPtrListIterator<K3bPlugin> it( d->plugins );
+ it.current(); ++it ) {
+ if( !grps.contains( it.current()->group() ) )
+ grps.append( it.current()->group() );
+ }
+
+ return grps;
+}
+
+
+QPtrList<K3bPlugin> K3bPluginManager::plugins( const QString& group ) const
+{
+ QPtrList<K3bPlugin> fl;
+ for( QPtrListIterator<K3bPlugin> 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<K3bPlugin*>( 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<K3bPlugin> 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 <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_PLUGIN_MANAGER_H_
+#define _K3B_PLUGIN_MANAGER_H_
+
+#include <qobject.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#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<K3bPlugin> 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 <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_PROJECT_PLUGIN_H_
+#define _K3B_PROJECT_PLUGIN_H_
+
+#include <k3bplugin.h>
+#include <qstring.h>
+#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 <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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 <stdint.h>
+#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 <math.h>]
+)
+
+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 <math.h>]
+)
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 <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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 <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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 <math.h>
+
+#elif (defined (WIN32) || defined (_WIN32))
+
+ #undef HAVE_LRINT_REPLACEMENT
+ #define HAVE_LRINT_REPLACEMENT 1
+ #include <math.h>
+
+ /*
+ ** 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 <math.h>
+
+ #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 <math.h>
+
+ #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 <math.h>
+
+ #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 <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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 <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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 <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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 <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <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 "k3baudiocdtrackdrag.h"
+
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3btoc.h>
+#include <k3btrack.h>
+#include <k3bcore.h>
+
+#include <qdatastream.h>
+#include <qcstring.h>
+
+
+// FIXME: multiple tracks
+K3bAudioCdTrackDrag::K3bAudioCdTrackDrag( const K3bDevice::Toc& toc, const QValueList<int>& 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<int>::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<int>& 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 <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_AUDIO_CDTRACK_DRAG_H_
+#define _K3B_AUDIO_CDTRACK_DRAG_H_
+
+#include <qdragobject.h>
+#include <qcstring.h>
+#include <qvaluelist.h>
+
+#include <k3btoc.h>
+#include <k3bcddbresult.h>
+#include <k3bdevice.h>
+#include "k3b_export.h"
+
+class LIBK3B_EXPORT K3bAudioCdTrackDrag : public QStoredDrag
+{
+ public:
+ K3bAudioCdTrackDrag( const K3bDevice::Toc& toc, const QValueList<int>& 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<int>& 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<int>& trackNumbers, K3bCddbResultEntry&, K3bDevice::Device** dev = 0 );
+
+ private:
+ K3bDevice::Toc m_toc;
+ QValueList<int> 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 <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 "k3baudiocdtracksource.h"
+#include "k3baudiotrack.h"
+#include "k3baudiodoc.h"
+
+#include <k3bthreadwidget.h>
+#include <k3btoc.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bcdparanoialib.h>
+#include <k3bdeviceselectiondialog.h>
+#include <k3bcore.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+
+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<K3bDevice::Device>& devices = k3bcore->deviceManager()->readingDevices();
+ for( QPtrListIterator<K3bDevice::Device> 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 <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_AUDIO_CD_TRACK_SOURCE_H_
+#define _K3B_AUDIO_CD_TRACK_SOURCE_H_
+
+#include "k3baudiodatasource.h"
+
+#include <k3btoc.h>
+#include <k3bcddbresult.h>
+
+#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 <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 "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 <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_AUDIO_DATA_SOURCE_H_
+#define _K3B_AUDIO_DATA_SOURCE_H_
+
+#include <k3bmsf.h>
+#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 <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 "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 <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_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 <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 <k3bglobals.h>
+#include "k3baudiodoc.h"
+#include "k3baudiotrack.h"
+#include "k3baudiojob.h"
+#include "k3baudiofile.h"
+#include "k3baudiozerodata.h"
+#include "k3baudiocdtracksource.h"
+
+#include <k3bcuefileparser.h>
+#include <k3bcdtextvalidator.h>
+#include <k3bcore.h>
+#include <k3baudiodecoder.h>
+
+
+// QT-includes
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdatastream.h>
+#include <qdir.h>
+#include <qdom.h>
+#include <qdatetime.h>
+#include <qtextstream.h>
+#include <qsemaphore.h>
+
+// KDE-includes
+#include <kprocess.h>
+#include <kurl.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kio/global.h>
+#include <kdebug.h>
+
+#include <iostream>
+
+
+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<K3bAudioFile*>( 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<K3bAudioFile*>(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<K3bAudioZeroData*>(source) ) {
+ QDomElement sourceElem = doc.createElement( "silence" );
+ sourceElem.setAttribute( "length", zero->length().toString() );
+ sourcesParent.appendChild( sourceElem );
+ }
+ else if( K3bAudioCdTrackSource* cdTrack = dynamic_cast<K3bAudioCdTrackSource*>(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("<p>Unable to handle the following files due to an unsupported format:"
+ "<p>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 <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 K3BAUDIODOC_H
+#define K3BAUDIODOC_H
+
+#include <k3bdoc.h>
+
+#include <k3bcdtext.h>
+#include <k3btoc.h>
+
+#include <qptrlist.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdatetime.h>
+#include <qtextstream.h>
+#include "k3b_export.h"
+#include <kurl.h>
+
+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<K3bAudioDecoder*, int> m_decoderUsageCounterMap;
+ // used to check if we already have a decoder for a specific file
+ QMap<QString, K3bAudioDecoder*> 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 <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 "k3baudiofile.h"
+#include "k3baudiodoc.h"
+#include "k3baudiotrack.h"
+
+#include <k3baudiodecoder.h>
+
+
+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 <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_AUDIO_FILE_H_
+#define _K3B_AUDIO_FILE_H_
+
+#include "k3baudiodatasource.h"
+
+#include <k3bmsf.h>
+#include <kurl.h>
+#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 <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 "k3baudioimager.h"
+#include "k3baudiodoc.h"
+#include "k3baudiotrack.h"
+#include "k3baudiodatasource.h"
+
+#include <k3bthread.h>
+#include <k3bwavefilewriter.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qfile.h>
+
+#include <unistd.h>
+
+
+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<void*>(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 <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_AUDIO_IMAGER_H_
+#define _K3B_AUDIO_IMAGER_H_
+
+#include <k3bthreadjob.h>
+
+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 <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 "k3baudiojob.h"
+
+#include "k3baudioimager.h"
+#include <k3baudiodoc.h>
+#include "k3baudiotrack.h"
+#include "k3baudiodatasource.h"
+#include "k3baudionormalizejob.h"
+#include "k3baudiojobtempdata.h"
+#include "k3baudiomaxspeedjob.h"
+#include "k3baudiocdtracksource.h"
+#include "k3baudiofile.h"
+#include <k3bdevicemanager.h>
+#include <k3bdevicehandler.h>
+#include <k3bdevice.h>
+#include <k3bcdtext.h>
+#include <k3bmsf.h>
+#include <k3bglobals.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bcore.h>
+#include <k3bcdrecordwriter.h>
+#include <k3bcdrdaowriter.h>
+#include <k3btocfilewriter.h>
+#include <k3binffilewriter.h>
+
+#include <qfile.h>
+#include <qvaluevector.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <ktempfile.h>
+#include <kstringhandler.h>
+
+
+
+static QString createNonExistingFilesString( const QValueList<K3bAudioFile*>& items, unsigned int max )
+{
+ QString s;
+ unsigned int cnt = 0;
+ for( QValueList<K3bAudioFile*>::const_iterator it = items.begin();
+ it != items.end(); ++it ) {
+
+ s += KStringHandler::csqueeze( (*it)->filename(), 60 );
+
+ ++cnt;
+ if( cnt >= max || it == items.end() )
+ break;
+
+ s += "<br>";
+ }
+
+ 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<K3bAudioFile*> nonExistingFiles;
+ K3bAudioTrack* track = m_doc->firstTrack();
+ while( track ) {
+ K3bAudioDataSource* source = track->firstSource();
+ while( source ) {
+ if( K3bAudioFile* file = dynamic_cast<K3bAudioFile*>( source ) ) {
+ if( !QFile::exists( file->filename() ) )
+ nonExistingFiles.append( file );
+ }
+ source = source->next();
+ }
+ track = track->next();
+ }
+ if( !nonExistingFiles.isEmpty() ) {
+ if( questionYesNo( "<p>" + 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?") +
+ "<p>" + createNonExistingFilesString( nonExistingFiles, 10 ),
+ i18n("Warning"),
+ i18n("Remove missing files and continue"),
+ i18n("Cancel and go back") ) ) {
+ for( QValueList<K3bAudioFile*>::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<QString> 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<K3bAudioCdTrackSource*>(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 <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 K3BAUDIOJOB_H
+#define K3BAUDIOJOB_H
+
+#include <k3bjob.h>
+
+
+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 <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 "k3baudiojobtempdata.h"
+#include "k3baudiodoc.h"
+#include "k3baudiotrack.h"
+#include <k3bglobals.h>
+#include <k3bversion.h>
+#include <k3bmsf.h>
+#include <k3bcore.h>
+
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qvaluevector.h>
+
+#include <kdebug.h>
+
+
+class K3bAudioJobTempData::Private
+{
+public:
+ Private( K3bAudioDoc* _doc )
+ : doc(_doc) {
+ }
+
+ QValueVector<QString> bufferFiles;
+ QValueVector<QString> 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 <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_AUDIO_JOB_TEMPDATA_H_
+#define _K3B_AUDIO_JOB_TEMPDATA_H_
+
+#include <qobject.h>
+#include <k3bmsf.h>
+
+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 <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 "k3baudiomaxspeedjob.h"
+#include "k3baudiotrack.h"
+#include "k3baudiodatasource.h"
+#include "k3baudiodoc.h"
+#include "k3baudiocdtracksource.h"
+#include "k3baudiodatasourceiterator.h"
+
+#include <k3bdevice.h>
+
+#include <k3bthread.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qdatetime.h>
+
+
+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<K3bAudioCdTrackSource*>( 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<int> 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<int> 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 <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_AUDIO_MAX_SPEED_JOB_H_
+#define _K3B_AUDIO_MAX_SPEED_JOB_H_
+
+#include <k3bthreadjob.h>
+
+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 <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 "k3baudionormalizejob.h"
+#include <k3bexternalbinmanager.h>
+#include <k3bprocess.h>
+#include <k3bcore.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+
+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 <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_AUDIO_NORMALIZE_JOB_H_
+#define _K3B_AUDIO_NORMALIZE_JOB_H_
+
+
+#include <k3bjob.h>
+
+#include <qvaluevector.h>
+
+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<QString>& files ) { m_files = files; }
+
+ private slots:
+ void slotStdLine( const QString& line );
+ void slotProcessExited( KProcess* p );
+
+ private:
+ K3bProcess* m_process;
+
+ QValueVector<QString> 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 <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 "k3baudiotrack.h"
+#include "k3baudiodoc.h"
+#include "k3baudiodatasource.h"
+
+#include <k3baudiodecoder.h>
+#include <k3bcore.h>
+#include <k3bcdtextvalidator.h>
+
+#include <qstring.h>
+
+#include <kdebug.h>
+
+
+
+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 <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 K3BAUDIOTRACK_H
+#define K3BAUDIOTRACK_H
+
+#include <qstring.h>
+#include <qfileinfo.h>
+#include <qfile.h>
+#include <qptrlist.h>
+
+#include <kio/global.h>
+
+#include <k3bmsf.h>
+
+#include <k3bcdtext.h>
+#include <k3btrack.h>
+#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 <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 "k3baudiozerodata.h"
+#include "k3baudiotrack.h"
+
+#include <klocale.h>
+
+#include <string.h>
+
+
+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 <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_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 <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 "k3bbootitem.h"
+#include "k3bdatadoc.h"
+#include "k3bdiritem.h"
+
+#include <klocale.h>
+
+#include <qptrlist.h>
+
+
+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 <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_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 <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 "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 <k3bcore.h>
+#include <k3bglobals.h>
+#include <k3bmsf.h>
+#include <k3biso9660.h>
+#include <k3bdevicehandler.h>
+#include <k3bdevice.h>
+#include <k3btoc.h>
+#include <k3btrack.h>
+#include <k3bmultichoicedialog.h>
+#include <k3bvalidators.h>
+
+#include <qdir.h>
+#include <qstring.h>
+#include <qfileinfo.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+#include <qdom.h>
+#include <qptrlist.h>
+
+#include <kstandarddirs.h>
+#include <kurl.h>
+#include <kstatusbar.h>
+#include <klocale.h>
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kprogress.h>
+#include <kconfig.h>
+#include <kapplication.h>
+
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+
+/**
+ * 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<K3bDirItem*>(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<K3bDirItem*>(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<K3bDataItem> 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<K3bFileItem*>( 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<K3bBootItem*>( 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<K3bDirItem*>( item ) ) {
+ QDomElement topElem = doc->createElement( "directory" );
+ topElem.setAttribute( "name", dirItem->k3bName() );
+
+ if( item->sortWeight() != 0 )
+ topElem.setAttribute( "sort_weight", QString::number(item->sortWeight()) );
+
+ QPtrListIterator<K3bDataItem> 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<K3bBootItem*>( 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<K3bBootItem*>( 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<K3bDataItem> itemList, K3bDirItem* newParent )
+{
+ if( !newParent ) {
+ kdDebug() << "(K3bDataDoc) tried to move items to nowhere...!" << endl;
+ return;
+ }
+
+ QPtrListIterator<K3bDataItem> it( itemList );
+ for( ; it.current(); ++it ) {
+ // check if newParent is subdir of item
+ if( K3bDirItem* dirItem = dynamic_cast<K3bDirItem*>( 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<K3bDataItem> sortedChildren;
+ QPtrListIterator<K3bDataItem> it( dir->children() );
+
+ for( it.toLast(); it.current(); --it ) {
+ K3bDataItem* item = it.current();
+
+ if( item->isDir() )
+ prepareFilenamesInDir( dynamic_cast<K3bDirItem*>( 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<K3bDataItem> 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<K3bDataItem> 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<const K3bIso9660Directory*>(entry), dir );
+ }
+ else {
+ const K3bIso9660File* file = static_cast<const K3bIso9660File*>(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<K3bDataItem> 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<K3bDirItem*>(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<K3bDataItem*> K3bDataDoc::findItemByLocalPath( const QString& path ) const
+{
+ Q_UNUSED( path );
+ return QValueList<K3bDataItem*>();
+}
+
+
+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 <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 K3BDATADOC_H
+#define K3BDATADOC_H
+
+#include <k3bdoc.h>
+#include <k3bdataitem.h>
+
+#include "k3bisooptions.h"
+
+#include <qptrlist.h>
+#include <qfileinfo.h>
+#include <qstringlist.h>
+
+#include <kurl.h>
+#include <kio/global.h>
+#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<K3bDataItem> 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<K3bBootItem>& 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<K3bDataItem*>& 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<K3bDataItem*> 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<K3bDataItem> m_oldSession;
+
+ // boot cd stuff
+ K3bDataItem* m_bootCataloge;
+ QPtrList<K3bBootItem> m_bootImages;
+
+ bool m_bExistingItemsReplaceAll;
+ bool m_bExistingItemsIgnoreAll;
+
+ bool m_needToCutFilenames;
+ QValueList<K3bDataItem*> 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 <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 "k3bdataitem.h"
+#include "k3bdiritem.h"
+#include "k3bdatadoc.h"
+#include <kdebug.h>
+
+#include <math.h>
+
+
+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<K3bDataItem*>(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 <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 K3BDATAITEM_H
+#define K3BDATAITEM_H
+
+
+class K3bDirItem;
+class K3bDataDoc;
+
+#include <qstring.h>
+
+#include <kio/global.h>
+
+#include <k3bmsf.h>
+#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 <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 "k3bdatajob.h"
+#include "k3bdatadoc.h"
+#include "k3bisoimager.h"
+#include "k3bmsinfofetcher.h"
+
+#include <k3bcore.h>
+#include <k3bglobals.h>
+#include <k3bversion.h>
+#include <k3bdevice.h>
+#include <k3bdevicehandler.h>
+#include <k3btoc.h>
+#include <k3btrack.h>
+#include <k3bdevicehandler.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bcdrecordwriter.h>
+#include <k3bcdrdaowriter.h>
+#include <k3bglobalsettings.h>
+#include <k3bactivepipe.h>
+#include <k3bfilesplitter.h>
+#include <k3bverificationjob.h>
+
+#include <kprocess.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kio/global.h>
+#include <kio/job.h>
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdatetime.h>
+#include <qfile.h>
+#include <qdatastream.h>
+#include <kdebug.h>
+
+
+
+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 <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 K3BDATAJOB_H
+#define K3BDATAJOB_H
+
+#include <k3bjob.h>
+#include <k3bdatadoc.h>
+
+#include <qfile.h>
+
+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 <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 "k3bdatapreparationjob.h"
+#include "k3bdatadoc.h"
+#include "k3bisooptions.h"
+
+#include <k3bthreadjob.h>
+#include <k3bthread.h>
+#include <k3bdiritem.h>
+#include <k3bfileitem.h>
+#include <k3bglobals.h>
+
+#include <klocale.h>
+#include <kstringhandler.h>
+
+#include <qfile.h>
+#include <qvaluelist.h>
+
+
+class K3bDataPreparationJob::Private : public K3bThread
+{
+public:
+ Private( K3bDataDoc* doc );
+
+ void run();
+ void cancel();
+
+ K3bDataDoc* doc;
+
+ QValueList<K3bDataItem*> nonExistingItems;
+ QString listOfRenamedItems;
+ QValueList<K3bDataItem*> 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<K3bDataItem*>::const_iterator it;
+ for( it = doc->needToCutFilenameItems().begin();
+ maxlines > 0 && it != doc->needToCutFilenameItems().end();
+ ++it, --maxlines ) {
+ K3bDataItem* item = *it;
+ listOfRenamedItems += i18n("<em>%1</em> renamed to <em>%2</em>")
+ .arg( KStringHandler::csqueeze( item->k3bName(), 30 ) )
+ .arg( KStringHandler::csqueeze( item->writtenName(), 30 ) );
+ listOfRenamedItems += "<br>";
+ }
+ 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<K3bDataItem*>& items, unsigned int max )
+{
+ QString s;
+ unsigned int cnt = 0;
+ for( QValueList<K3bDataItem*>::const_iterator it = items.begin();
+ it != items.end(); ++it ) {
+
+ s += KStringHandler::csqueeze( (*it)->localPath(), 60 );
+
+ ++cnt;
+ if( cnt >= max || it == items.end() )
+ break;
+
+ s += "<br>";
+ }
+
+ 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( "<p>" + 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 )
+ + "<p>" + 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( "<p>" + 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( "<p>" + 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?") +
+ "<p>" + createItemsString( d->nonExistingItems, 10 ),
+ i18n("Warning"),
+ i18n("Remove missing files and continue"),
+ i18n("Cancel and go back") ) ) {
+ for( QValueList<K3bDataItem*>::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( "<p>" + 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?") +
+ "<p>" + 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 <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_DATA_PREPARATION_JOB_H_
+#define _K3B_DATA_PREPARATION_JOB_H_
+
+#include <k3bjob.h>
+
+
+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 <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 "k3bdiritem.h"
+#include "k3bdatadoc.h"
+#include "k3bsessionimportitem.h"
+#include "k3bfileitem.h"
+
+#include <qstring.h>
+#include <qptrlist.h>
+
+#include <kdebug.h>
+
+
+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<K3bDataItem> 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<K3bDirItem*>(this);
+}
+
+K3bDirItem* K3bDirItem::addDataItem( K3bDataItem* item )
+{
+ // check if we are a subdir of item
+ if( K3bDirItem* dirItem = dynamic_cast<K3bDirItem*>(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<K3bSessionImportItem*>(oldItem)->setReplaceItem( static_cast<K3bFileItem*>(item) );
+ static_cast<K3bFileItem*>(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<K3bFileItem*>(item)->replaceItemFromOldSession() )
+ addDataItem( static_cast<K3bFileItem*>(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<K3bDataItem> 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<K3bDirItem*>(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<K3bDirItem*>(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<K3bDataItem> 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<K3bDataItem> 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<K3bDataItem> 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 <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 K3BDIRITEM_H
+#define K3BDIRITEM_H
+
+
+#include <qstring.h>
+#include <qptrlist.h>
+
+#include <kio/global.h>
+
+#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<K3bDataItem>& 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<K3bDataItem> 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 <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 "k3bfilecompilationsizehandler.h"
+#include "k3bfileitem.h"
+
+#include <kdebug.h>
+
+#include <qfile.h>
+#include <qmap.h>
+#include <qptrlist.h>
+
+
+// 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<K3bDataItem> 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<K3bFileItem::Id, InodeInfo> inodeMap;
+
+ KIO::filesize_t size;
+ K3b::Msf blocks;
+
+ QPtrList<K3bDataItem> 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<K3bFileItem*>( 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<K3bFileItem*>( 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 <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_FILECOMPILATION_SIZE_HANDLER_H_
+#define _K3B_FILECOMPILATION_SIZE_HANDLER_H_
+
+
+#include <kio/global.h>
+#include <k3bmsf.h>
+
+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 <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 <config.h>
+#include <k3bglobals.h>
+
+#include "k3bfileitem.h"
+#include "k3bdatadoc.h"
+#include "k3bdiritem.h"
+#include "k3bisooptions.h"
+#include <k3bglobals.h>
+
+#include <qfileinfo.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <qfile.h>
+
+#include <kurl.h>
+#include <kdebug.h>
+
+#include <errno.h>
+#include <string.h>
+
+
+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 <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 K3BFILEITEM_H
+#define K3BFILEITEM_H
+
+
+#include "k3bdataitem.h"
+#include <k3bglobals.h>
+
+#include <kio/global.h>
+#include <qstring.h>
+
+#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 <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 <config.h>
+#include <k3bglobals.h>
+
+#include "k3bisoimager.h"
+#include "k3bdiritem.h"
+#include "k3bbootitem.h"
+#include "k3bdatadoc.h"
+#include "k3bdatapreparationjob.h"
+#include <k3bexternalbinmanager.h>
+#include <k3bdevice.h>
+#include <k3bprocess.h>
+#include <k3bcore.h>
+#include <k3bversion.h>
+#include <k3bglobals.h>
+#include <k3bchecksumpipe.h>
+#include <k3bfilesplitter.h>
+
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+#include <ktempfile.h>
+#include <kio/netaccess.h>
+#include <kio/global.h>
+#include <kio/job.h>
+#include <kstringhandler.h>
+
+#include <qfile.h>
+#include <qregexp.h>
+#include <qdir.h>
+#include <qapplication.h>
+#include <qvaluestack.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <utime.h>
+
+
+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<QCString>& args = m_process->args();
+ QString s;
+ for( QValueList<QCString>::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<QCString>& args = m_process->args();
+ QString s;
+ for( QValueList<QCString>::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<K3bBootItem> 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<K3bDataItem> 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<K3bDirItem*>(item) ) ) << "\n";
+
+ int x = writePathSpecForDir( dynamic_cast<K3bDirItem*>(item), stream );
+ if( x >= 0 )
+ num += x;
+ else
+ return -1;
+ }
+ else {
+ writePathSpecForFile( static_cast<K3bFileItem*>(item), stream );
+ }
+ }
+ }
+
+ return num;
+}
+
+
+void K3bIsoImager::writePathSpecForFile( K3bFileItem* item, QTextStream& stream )
+{
+ stream << escapeGraftPoint( item->writtenPath() )
+ << "=";
+
+ if( m_doc->bootImages().containsRef( dynamic_cast<K3bBootItem*>(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<K3bBootItem*>(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<K3bBootItem*>(item) ) ) { // boot-image-backup-hack
+ *t << escapeGraftPoint( static_cast<K3bBootItem*>(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<K3bDirItem*>(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<K3bChecksumPipe*>( 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 <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_ISO_IMAGER_H
+#define K3B_ISO_IMAGER_H
+
+#include <k3bjob.h>
+#include "k3bmkisofshandler.h"
+
+#include <qptrqueue.h>
+#include <qstringlist.h>
+
+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 <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 "k3bisooptions.h"
+#include <k3bcore.h>
+#include <k3bversion.h>
+#include <k3bglobals.h>
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <qstring.h>
+
+
+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 <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_ISO_OPTIONS_H
+#define K3B_ISO_OPTIONS_H
+
+#include <qstring.h>
+#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 <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 "k3bmkisofshandler.h"
+
+#include <k3bexternalbinmanager.h>
+#include <k3bcore.h>
+#include <k3bjob.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <cmath>
+
+
+
+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 <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_MKISOfS_HANDLER_H_
+#define _K3B_MKISOfS_HANDLER_H_
+
+#include <qstring.h>
+
+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 <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 "k3bmsinfofetcher.h"
+
+#include <k3bexternalbinmanager.h>
+#include <k3bdevicemanager.h>
+#include <k3bdevicehandler.h>
+#include <k3bdevice.h>
+#include <k3bcore.h>
+#include <k3bglobals.h>
+#include <k3biso9660.h>
+
+#include <klocale.h>
+#include <kprocess.h>
+#include <kdebug.h>
+
+#include <qstringlist.h>
+
+
+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<QCString>& args = m_process->args();
+ QString s;
+ for( QValueList<QCString>::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 <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_MSINFO_FETCHER_H
+#define K3B_MSINFO_FETCHER_H
+
+#include <k3bjob.h>
+
+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 <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 "k3bsessionimportitem.h"
+#include "k3bfileitem.h"
+#include "k3bdiritem.h"
+
+#include <k3biso9660.h>
+
+
+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 <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_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 <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 K3BSPECIALDATAITEM_H
+#define K3BSPECIALDATAITEM_H
+
+#include "k3bdataitem.h"
+#include "k3bdiritem.h"
+
+#include <kio/global.h>
+
+/**
+ * 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 <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 "k3bdvdbooktypejob.h"
+
+#include <k3bglobals.h>
+#include <k3bprocess.h>
+#include <k3bdevice.h>
+#include <k3bdeviceglobals.h>
+#include <k3bdevicehandler.h>
+#include <k3bdiskinfo.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bcore.h>
+#include <k3bversion.h>
+#include <k3bglobalsettings.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qvaluelist.h>
+#include <qregexp.h>
+
+#include <errno.h>
+#include <string.h>
+
+
+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<p><b>%1 %2 (%3)</b>.")
+ .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<QCString>& args = d->process->args();
+ QString s;
+ for( QValueList<QCString>::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 <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_DVD_BOOKTYPE_JOB_H_
+#define _K3B_DVD_BOOKTYPE_JOB_H_
+
+
+#include <k3bjob.h>
+
+
+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 <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 "k3bdvddoc.h"
+#include "k3bdvdjob.h"
+
+#include <k3bisooptions.h>
+
+#include <kconfig.h>
+
+
+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 <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_DVDDOC_H_
+#define _K3B_DVDDOC_H_
+
+#include <k3bdatadoc.h>
+#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 <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 "k3bdvdjob.h"
+#include "k3bdvddoc.h"
+
+#include <k3bcore.h>
+#include <k3bisoimager.h>
+#include <k3bgrowisofswriter.h>
+#include <k3bglobals.h>
+#include <k3bdevice.h>
+#include <k3bdevicehandler.h>
+#include <k3bdiskinfo.h>
+#include <k3bdeviceglobals.h>
+#include <k3bglobalsettings.h>
+#include <k3biso9660.h>
+#include <k3bmsinfofetcher.h>
+
+#include <klocale.h>
+#include <kapplication.h>
+
+
+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 <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_DVD_JOB_H_
+#define _K3B_DVD_JOB_H_
+
+#include <k3bdatajob.h>
+
+#include <qfile.h>
+
+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 <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 "k3bdvdview.h"
+#include "k3bdvddoc.h"
+#include "k3bdvdburndialog.h"
+#include <k3bfillstatusdisplay.h>
+#include <k3bdatafileview.h>
+
+#include <klocale.h>
+
+
+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 <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_DVDVIEW_H_
+#define _K3B_DVDVIEW_H_
+
+#include <k3bdataview.h>
+
+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 <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 "k3babstractwriter.h"
+
+#include <k3bcore.h>
+#include <k3bdevicemanager.h>
+#include <k3bdevicehandler.h>
+#include <k3bglobalsettings.h>
+
+#include <klocale.h>
+#include <kglobal.h>
+
+
+
+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 <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_ABSTRACT_WRITER_H
+#define K3B_ABSTRACT_WRITER_H
+
+
+#include "k3bjob.h"
+
+#include <qdatetime.h>
+
+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 <trueg@k3b.org>
+ * Klaus-Dieter Krannich <kd@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 "k3bcdrdaowriter.h"
+
+#include <k3bcore.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bdevicemanager.h>
+#include <k3bprocess.h>
+#include <k3bdevice.h>
+#include <k3bdevicehandler.h>
+#include <k3bthroughputestimator.h>
+#include <k3bglobals.h>
+#include <k3bglobalsettings.h>
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qregexp.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qurl.h>
+#include <qsocket.h>
+#include <qsocketdevice.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kio/netaccess.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+
+
+#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<QCString>& args = m_process->args();
+ QString s;
+ for( QValueList<QCString>::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 <trueg@k3b.org>
+ * Klaus-Dieter Krannich <kd@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_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 <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 <config.h>
+
+
+#include "k3bcdrecordwriter.h"
+
+#include <k3bcore.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bprocess.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bdevicehandler.h>
+#include <k3bglobals.h>
+#include <k3bthroughputestimator.h>
+#include <k3bglobalsettings.h>
+#include <k3btempfile.h>
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qurl.h>
+#include <qvaluelist.h>
+#include <qregexp.h>
+#include <qfile.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kglobal.h>
+
+
+
+class K3bCdrecordWriter::Private
+{
+public:
+ Private()
+ : cdTextFile(0) {
+ }
+
+ K3bThroughputEstimator* speedEst;
+ bool canceled;
+ bool usingBurnfree;
+ int usedSpeed;
+
+ struct Track {
+ int size;
+ bool audio;
+ };
+
+ QValueList<Track> 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<QCString>& args = m_process->args();
+ QString s;
+ for( QValueList<QCString>::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<int>( 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 <CR> 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 <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_CDRECORD_WRITER_H
+#define K3B_CDRECORD_WRITER_H
+
+
+#include "k3babstractwriter.h"
+
+#include <qstringlist.h>
+
+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 <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 "k3bcuefileparser.h"
+
+#include <k3bmsf.h>
+#include <k3bglobals.h>
+#include <k3btrack.h>
+#include <k3bcdtext.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <qdir.h>
+
+#include <kdebug.h>
+
+
+// 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 <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_CUEFILE_PARSER_H_
+#define _K3B_CUEFILE_PARSER_H_
+
+#include "k3bimagefilereader.h"
+
+#include <k3btoc.h>
+#include <k3bcdtext.h>
+#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 <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 files for Qt
+#include <qwidget.h>
+#include <qstring.h>
+#include <qdom.h>
+
+// include files for KDE
+#include <klocale.h>
+#include <kdebug.h>
+
+// application specific includes
+#include "k3bdoc.h"
+#include <k3bglobals.h>
+#include <k3bdevice.h>
+#include <k3bmsf.h>
+#include <k3baudiodoc.h>
+#include <k3bdatadoc.h>
+#include <k3bvcddoc.h>
+#include <k3bmixeddoc.h>
+#include <k3bmovixdoc.h>
+#include <k3bmovixdvddoc.h>
+#include <k3bdvddoc.h>
+#include <k3bvideodvddoc.h>
+#include <k3bcore.h>
+#include <k3bdevicemanager.h>
+
+
+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 <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 K3BDOC_H
+#define K3BDOC_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// include files for QT
+#include <qobject.h>
+#include <qstring.h>
+#include <qptrlist.h>
+
+
+// include files for KDE
+#include <kurl.h>
+#include <kio/global.h>
+#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 <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 "k3bdvdrecordwriter.h"
+
+#include <k3bcore.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bprocess.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bglobals.h>
+#include <k3bglobalsettings.h>
+
+#include <klocale.h>
+
+
+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 <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_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 <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 "k3bgrowisofshandler.h"
+
+#include <k3bjob.h>
+#include <k3bcore.h>
+#include <k3bglobalsettings.h>
+#include <k3bdevice.h>
+#include <k3bdevicehandler.h>
+
+#include <klocale.h>
+#include <kglobal.h>
+#include <kdebug.h>
+
+#include <qtimer.h>
+
+#include <errno.h>
+#include <string.h>
+
+
+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 <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_GROWISOFS_HANDLER_H_
+#define _K3B_GROWISOFS_HANDLER_H_
+
+#include <qobject.h>
+
+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 <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 "k3bgrowisofswriter.h"
+
+#include <k3bcore.h>
+#include <k3bdevice.h>
+#include <k3bdevicehandler.h>
+#include <k3bprocess.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bversion.h>
+#include <k3bdiskinfo.h>
+#include <k3bglobals.h>
+#include <k3bthroughputestimator.h>
+#include "k3bgrowisofshandler.h"
+#include <k3bpipebuffer.h>
+#include <k3bglobalsettings.h>
+#include <k3bdeviceglobals.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kglobal.h>
+
+#include <qvaluelist.h>
+#include <qfile.h>
+
+#include <unistd.h>
+
+
+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<QCString>& args = d->process->args();
+ QString s;
+ for( QValueList<QCString>::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 <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_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 <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 "k3bimagefilereader.h"
+
+#include <qfile.h>
+#include <qtextstream.h>
+
+#include <kdebug.h>
+
+
+
+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 <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_IMAGE_FILE_READER_H_
+#define _K3B_IMAGE_FILE_READER_H_
+
+#include <qstring.h>
+#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 <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 "k3binffilewriter.h"
+
+#include <k3bcdtext.h>
+#include <k3btrack.h>
+#include <k3bmsf.h>
+#include <k3bcore.h>
+#include <k3bversion.h>
+
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qdatetime.h>
+
+
+
+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<K3b::Msf>& 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 <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_INF_FILE_WRITER_H_
+#define _K3B_INF_FILE_WRITER_H_
+
+#include <qvaluevector.h>
+#include <qtextstream.h>
+
+#include <k3bmsf.h>
+
+
+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<long> 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 <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 "k3bpipebuffer.h"
+
+#include <k3bthread.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+
+//
+// This one is based on the little pipebuf2 program by Peter Osterlund <petero2@telia.com>
+//
+
+
+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 <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_PIPE_BUFFER_H_
+#define _K3B_PIPE_BUFFER_H_
+
+
+#include <k3bthreadjob.h>
+
+/**
+ * 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 <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 "k3btocfilewriter.h"
+
+#include <k3btrack.h>
+#include <k3bmsf.h>
+#include <k3bcore.h>
+#include <k3bversion.h>
+
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qdatetime.h>
+
+
+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 <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_TOC_FILE_WRITER_H_
+#define _K3B_TOC_FILE_WRITER_H_
+
+#include <qtextstream.h>
+#include <qstringlist.h>
+
+#include <k3btoc.h>
+#include <k3bcdtext.h>
+
+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 <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 "k3bmixeddoc.h"
+#include "k3bmixedjob.h"
+
+#include <k3bdatadoc.h>
+#include <k3baudiodoc.h>
+#include <k3bglobals.h>
+#include <k3bmsf.h>
+
+#include <qfileinfo.h>
+#include <qdom.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+
+
+
+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 <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_MIXED_DOC_H
+#define K3B_MIXED_DOC_H
+
+#include <k3bdoc.h>
+#include <k3bdatadoc.h>
+#include <k3baudiodoc.h>
+
+#include <k3btoc.h>
+#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 <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 "k3bmixedjob.h"
+#include "k3bmixeddoc.h"
+
+#include <k3bdatadoc.h>
+#include <k3bisoimager.h>
+#include <k3bmsinfofetcher.h>
+#include <k3baudioimager.h>
+#include <k3baudiodoc.h>
+#include <k3baudiotrack.h>
+#include <k3baudionormalizejob.h>
+#include <k3baudiojobtempdata.h>
+#include <k3baudiomaxspeedjob.h>
+#include <k3bdevicemanager.h>
+#include <k3bdevice.h>
+#include <k3bdevicehandler.h>
+#include <k3bmsf.h>
+#include <k3bglobals.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bversion.h>
+#include <k3bcore.h>
+#include <k3bcdrecordwriter.h>
+#include <k3bcdrdaowriter.h>
+#include <k3btocfilewriter.h>
+#include <k3binffilewriter.h>
+#include <k3bglobalsettings.h>
+#include <k3baudiofile.h>
+
+#include <qfile.h>
+#include <qdatastream.h>
+#include <qapplication.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <ktempfile.h>
+#include <kio/netaccess.h>
+#include <kio/global.h>
+#include <kstringhandler.h>
+
+
+static QString createNonExistingFilesString( const QValueList<K3bAudioFile*>& items, unsigned int max )
+{
+ QString s;
+ unsigned int cnt = 0;
+ for( QValueList<K3bAudioFile*>::const_iterator it = items.begin();
+ it != items.end(); ++it ) {
+
+ s += KStringHandler::csqueeze( (*it)->filename(), 60 );
+
+ ++cnt;
+ if( cnt >= max || it == items.end() )
+ break;
+
+ s += "<br>";
+ }
+
+ 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<K3bAudioFile*> nonExistingFiles;
+ K3bAudioTrack* track = m_doc->audioDoc()->firstTrack();
+ while( track ) {
+ K3bAudioDataSource* source = track->firstSource();
+ while( source ) {
+ if( K3bAudioFile* file = dynamic_cast<K3bAudioFile*>( source ) ) {
+ if( !QFile::exists( file->filename() ) )
+ nonExistingFiles.append( file );
+ }
+ source = source->next();
+ }
+ track = track->next();
+ }
+ if( !nonExistingFiles.isEmpty() ) {
+ if( questionYesNo( "<p>" + 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?") +
+ "<p>" + createNonExistingFilesString( nonExistingFiles, 10 ),
+ i18n("Warning"),
+ i18n("Remove missing files and continue"),
+ i18n("Cancel and go back") ) ) {
+ for( QValueList<K3bAudioFile*>::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<QString> 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 <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 K3BMIXEDJOB_H
+#define K3BMIXEDJOB_H
+
+#include <k3bjob.h>
+
+
+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 <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 "k3bmovixdoc.h"
+#include "k3bmovixjob.h"
+#include "k3bmovixfileitem.h"
+
+#include <k3bdiritem.h>
+#include <k3bfileitem.h>
+#include <k3bglobals.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kurl.h>
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <kapplication.h>
+
+#include <qdom.h>
+#include <qfileinfo.h>
+
+
+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<K3bMovixFileItem> 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<K3bMovixFileItem*>(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 <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_MOVIX_DOC_H_
+#define _K3B_MOVIX_DOC_H_
+
+
+#include <k3bdatadoc.h>
+
+#include <qptrlist.h>
+#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<K3bMovixFileItem>& 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<K3bMovixFileItem> 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 <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 "k3bmovixdocpreparer.h"
+#include "k3bmovixdoc.h"
+#include "k3bmovixprogram.h"
+#include "k3bmovixfileitem.h"
+
+
+#include <k3bcore.h>
+#include <k3bdiritem.h>
+#include <k3bfileitem.h>
+#include <k3bbootitem.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bisoimager.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <ktempfile.h>
+#include <kio/global.h>
+
+#include <qtextstream.h>
+#include <qdir.h>
+
+
+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<K3bDataItem> 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<const K3bMovixBin*>( 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<K3bMovixFileItem>& movixFileItems = d->doc->movixFileItems();
+
+ for( QPtrListIterator<K3bMovixFileItem> 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<K3bDirItem*>( 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<K3bDirItem*>( 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 <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_MOVIX_DOC_PREPARER_H_
+#define _K3B_MOVIX_DOC_PREPARER_H_
+
+#include <k3bjob.h>
+
+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 <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 "k3bmovixfileitem.h"
+#include "k3bmovixdoc.h"
+
+#include <k3bdiritem.h>
+
+
+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 <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_MOVIX_FILEITEM_H_
+#define _K3B_MOVIX_FILEITEM_H_
+
+#include <k3bfileitem.h>
+
+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 <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 "k3bmovixjob.h"
+#include "k3bmovixdoc.h"
+#include "k3bmovixfileitem.h"
+#include "k3bmovixdocpreparer.h"
+
+#include <k3bcore.h>
+#include <k3bdatajob.h>
+#include <k3bdevice.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+
+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 <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_MOVIX_JOB_H_
+#define _K3B_MOVIX_JOB_H_
+
+#include <k3bjob.h>
+
+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 <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 "k3bmovixprogram.h"
+
+#include <k3bprocess.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qtextstream.h>
+
+
+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 <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_MOVIX_PROGRAM_H_
+#define _K3B_MOVIX_PROGRAM_H_
+
+#include <k3bexternalbinmanager.h>
+#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 <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 "k3bmovixdvddoc.h"
+#include "k3bmovixdvdjob.h"
+
+#include <kconfig.h>
+
+
+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 <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_MOVIX_DVD_DOC_H_
+#define _K3B_MOVIX_DVD_DOC_H_
+
+#include <k3bmovixdoc.h>
+#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 <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 "k3bmovixdvdjob.h"
+#include "k3bmovixdvddoc.h"
+#include "k3bmovixfileitem.h"
+#include "k3bmovixdocpreparer.h"
+
+#include <k3bcore.h>
+#include <k3bdvdjob.h>
+#include <k3bdevice.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+
+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 <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_MOVIX_DVD_JOB_H_
+#define _K3B_MOVIX_DVD_JOB_H_
+
+#include <k3bjob.h>
+
+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
--- /dev/null
+++ b/libk3b/projects/videocd/cdi/cdi_imag.rtf
Binary files 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
--- /dev/null
+++ b/libk3b/projects/videocd/cdi/cdi_text.fnt
Binary files 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
--- /dev/null
+++ b/libk3b/projects/videocd/cdi/cdi_vcd.app
Binary files 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 @@
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META HTTP-EQUIV="Refresh" CONTENT="0; URL=http://www.icdia.org/">
+<TITLE>The New International CD-i Association</TITLE>
+</HEAD>
+<BODY>
+
+<A HREF="http://www.icdia.org">The New International CD-i Association - http://www.icdia.org</A>
+
+</BODY>
+</HTML>
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
--- /dev/null
+++ b/libk3b/projects/videocd/cdi/vcd_on_cdi_41.pdf
Binary files 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
--- /dev/null
+++ b/libk3b/projects/videocd/extra/k3bphotosvcd.mpg
Binary files differ
diff --git a/libk3b/projects/videocd/extra/k3bphotovcd.mpg b/libk3b/projects/videocd/extra/k3bphotovcd.mpg
new file mode 100644
index 0000000..2ddb69e
--- /dev/null
+++ b/libk3b/projects/videocd/extra/k3bphotovcd.mpg
Binary files 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 <chris@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.
+*/
+
+// QT-includes
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qfile.h>
+#include <qdatastream.h>
+#include <qdom.h>
+#include <qdatetime.h>
+#include <qtimer.h>
+#include <qtextstream.h>
+
+// KDE-includes
+#include <kprocess.h>
+#include <kurl.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kio/global.h>
+#include <kdebug.h>
+#include <kstdguiitem.h>
+
+// K3b-includes
+#include "k3bvcddoc.h"
+#include "k3bvcdtrack.h"
+#include "k3bvcdjob.h"
+#include <k3bglobals.h>
+#include <k3bmsf.h>
+
+
+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<K3bVcdTrack>;
+ 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<K3bVcdTrack> 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<K3bVcdTrack> 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<int, K3bVcdTrack*> numKeyMap = track->DefinedNumKey();
+ QMap<int, K3bVcdTrack*>::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 <chris@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 K3BVCDDOC_H
+#define K3BVCDDOC_H
+
+// Qt Includes
+#include <qptrqueue.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdatetime.h>
+#include <qtextstream.h>
+#include <qimage.h>
+
+// Kde Includes
+#include <kurl.h>
+
+// K3b Includes
+#include "k3bvcdoptions.h"
+#include "mpeginfo/k3bmpeginfo.h"
+#include <k3bdoc.h>
+#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<K3bVcdTrack>* 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<PrivateUrlToAdd> urlsToAdd;
+ QTimer* m_urlAddingTimer;
+
+ QPtrList<K3bVcdTrack>* 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 <chris@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 <klocale.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+#include <ktempfile.h>
+#include <kio/global.h>
+
+#include <qstring.h>
+#include <qdatetime.h>
+#include <qfile.h>
+#include <qtimer.h>
+#include <kdebug.h>
+#include <qregexp.h>
+#include <qdom.h>
+
+#include "k3bvcdjob.h"
+
+// K3b Includes
+#include "k3bvcddoc.h"
+#include "k3bvcdtrack.h"
+#include "k3bvcdxmlview.h"
+#include <k3bcore.h>
+#include <k3bdoc.h>
+#include <k3bprocess.h>
+#include <k3bdevice.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bglobals.h>
+#include <k3bcdrecordwriter.h>
+#include <k3bcdrdaowriter.h>
+
+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<QCString>& args = m_process->args();
+ QString s;
+ for ( QValueList<QCString>::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( "<?xml version='1.0'?><vcdxbuild>" ) + *str + "</vcdxbuild>" );
+
+ 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 <chris@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 K3BVCDJOB_H
+#define K3BVCDJOB_H
+
+#include <k3bjob.h>
+
+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 <chris@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.
+*/
+
+// Kde Includes
+#include <kapplication.h>
+#include <kconfig.h>
+#include <k3bcore.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+// Qt Includes
+#include <qstring.h>
+#include <qfile.h>
+
+// K3b Includes
+#include "k3bvcdoptions.h"
+#include <k3bversion.h>
+
+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 <chris@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_VCD_OPTIONS_H
+#define K3B_VCD_OPTIONS_H
+
+#include <qstring.h>
+#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 <chris@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 <kapplication.h>
+#include <kconfig.h>
+
+#include <qstring.h>
+#include <qfileinfo.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+// K3b Includes
+#include "k3bvcdtrack.h"
+#include <k3bglobals.h>
+
+K3bVcdTrack::K3bVcdTrack( QPtrList<K3bVcdTrack>* 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<K3bVcdTrack>;
+
+ 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 <chris@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 K3BVCDTRACK_H
+#define K3BVCDTRACK_H
+
+// Qt Includes
+#include <qstring.h>
+#include <qfileinfo.h>
+#include <qfile.h>
+#include <qptrlist.h>
+
+// Kde Includes
+#include <kio/global.h>
+
+// K3b Includes
+#include "mpeginfo/k3bmpeginfo.h"
+#include "k3b_export.h"
+class LIBK3B_EXPORT K3bVcdTrack
+{
+ public:
+ K3bVcdTrack( QPtrList<K3bVcdTrack>* 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<int, K3bVcdTrack*> 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<K3bVcdTrack>* m_parent;
+
+ // PBC
+ QPtrList<K3bVcdTrack>* m_revreflist; // List of Tracks which points to us
+ QMap<int, K3bVcdTrack*> m_pbctrackmap; // Pbc Tracks (Previous, Next, ...)
+ QMap<int, int> m_pbcnontrackmap; // Pbc NON Track types (Previous, Next, ...)
+ QMap<int, bool> m_pbcusrdefmap; // Pbc is userdefined or defaults (Previous, Next, ...)
+ QMap<int, K3bVcdTrack*> 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 <chris@k3b.org>
+* THX to Manfred Odenstein <odix@chello.at>
+*
+* 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 <qfile.h>
+
+#include <kstandarddirs.h>
+#include <kdebug.h>
+
+
+#include "k3bvcdxmlview.h"
+#include "k3bvcdtrack.h"
+#include <k3bcore.h>
+#include <k3bversion.h>
+
+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<K3bVcdTrack> 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 <endlist> 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<int, K3bVcdTrack*> numKeyMap = track->DefinedNumKey();
+ QMap<int, K3bVcdTrack*>::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<int, K3bVcdTrack*> numKeyMap = track->DefinedNumKey();
+ QMap<int, K3bVcdTrack*>::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 <chris@k3b.org>
+* THX to Manfred Odenstein <odix@chello.at>
+*
+* 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_VCD_XMLVIEW_H
+#define K3B_VCD_XMLVIEW_H
+
+#include <qstring.h>
+#include <qdom.h>
+#include <ktempfile.h>
+
+#include <k3bvcddoc.h>
+
+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 <chris@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.
+*/
+
+// kde includes
+#include <klocale.h>
+
+// 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 <chris@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 K3BMPEGINFO
+#define K3BMPEGINFO
+
+#include <stdio.h>
+
+// #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 <kdebug.h>
+
+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 <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 "k3bvideodvddoc.h"
+#include "k3bvideodvdjob.h"
+
+#include <k3bdiritem.h>
+
+#include <k3bisooptions.h>
+
+#include <kconfig.h>
+
+
+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 <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_DOC_H_
+#define _K3B_VIDEODVD_DOC_H_
+
+#include <k3bdvddoc.h>
+#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 <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 "k3bvideodvdimager.h"
+#include "k3bvideodvddoc.h"
+#include <k3bdiritem.h>
+#include <k3bfileitem.h>
+#include <k3bprocess.h>
+#include <k3bglobals.h>
+
+#include <ktempfile.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qtextstream.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qptrlist.h>
+
+
+
+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<K3bDataItem> 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<K3bDataItem> 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<K3bDirItem*>(item) ) ) << "\n";
+ }
+
+ int x = writePathSpecForDir( dynamic_cast<K3bDirItem*>(item), stream );
+ if( x >= 0 )
+ num += x;
+ else
+ return -1;
+ }
+ else {
+ writePathSpecForFile( static_cast<K3bFileItem*>(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<K3bDataItem> 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 <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_IMAGER_H_
+#define _K3B_VIDEODVD_IMAGER_H_
+
+
+#include <k3bisoimager.h>
+
+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 <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 "k3bvideodvdjob.h"
+#include "k3bvideodvddoc.h"
+#include "k3bvideodvdimager.h"
+
+#include <k3bcore.h>
+#include <k3bisoimager.h>
+#include <k3bgrowisofswriter.h>
+#include <k3bglobals.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kconfig.h>
+
+
+
+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 <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_VIDEO_DVD_JOB_H_
+#define _K3B_VIDEO_DVD_JOB_H_
+
+#include <k3bdvdjob.h>
+
+
+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 <device>"
+ exit 1
+fi
+
+DEVICE=$2
+
+if [ -z $DEVICE ]; then
+ echo "Usage: $0 disable|enable <device>"
+ 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 <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 "k3bactivepipe.h"
+
+#include <k3bpipe.h>
+
+#include <kdebug.h>
+
+#include <qthread.h>
+#include <qiodevice.h>
+
+#include <unistd.h>
+
+
+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 <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_ACTIVE_PIPE_H_
+#define _K3B_ACTIVE_PIPE_H_
+
+#include <qcstring.h>
+
+#include <k3b_export.h>
+
+
+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 <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 "k3bbusywidget.h"
+
+#include <qtimer.h>
+#include <qpainter.h>
+
+#include <kglobalsettings.h>
+
+
+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 <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_BUSY_WIDGET_H
+#define K3B_BUSY_WIDGET_H
+
+
+#include <qframe.h>
+#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 <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 <config.h>
+
+#include "k3bcdparanoialib.h"
+
+#include <k3bdevice.h>
+#include <k3btoc.h>
+#include <k3bmsf.h>
+
+#include <kdebug.h>
+
+#include <dlfcn.h>
+
+#include <qfile.h>
+#include <qmutex.h>
+
+
+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<K3bDevice::Device*, K3bCdparanoiaLibData*>::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<K3bDevice::Device*, K3bCdparanoiaLibData*>::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<K3bDevice::Device*, K3bCdparanoiaLibData*> s_dataMap;
+
+ K3bDevice::Device* m_device;
+
+ cdrom_drive* m_drive;
+ cdrom_paranoia* m_paranoia;
+
+ long m_currentSector;
+
+ QMutex mutex;
+};
+
+
+QMap<K3bDevice::Device*, K3bCdparanoiaLibData*> 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<char*>(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 <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_CDPARANOIA_LIB_H
+#define K3B_CDPARANOIA_LIB_H
+
+// from cdda_interface.h
+#define CD_FRAMESIZE_RAW 2352
+
+
+#include <qstring.h>
+
+#include <sys/types.h>
+#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:
+ * <pre>
+ * K3bCdparanoiaLib lib;
+ * lib.initParanoia( mydevice );
+ * lib.initReading( tracknumber );
+ * while( char* data = lib.read() )
+ * dosomethingcoolwithdata( data );
+ * </pre>
+ */
+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 <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 "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 <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 _K3BCDTEXTVALIDATOR_H_
+#define _K3BCDTEXTVALIDATOR_H_
+
+
+#include <k3bvalidators.h>
+#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 <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 "k3bchecksumpipe.h"
+
+#include <kmdcodec.h>
+#include <kdebug.h>
+
+#include <unistd.h>
+
+
+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 <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_CHECKSUM_PIPE_H_
+#define _K3B_CHECKSUM_PIPE_H_
+
+#include <k3bactivepipe.h>
+
+#include <k3b_export.h>
+
+
+/**
+ * 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 <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 "k3bcutcombobox.h"
+
+#include <k3bstringutils.h>
+
+#include <qfontmetrics.h>
+#include <qevent.h>
+#include <qstringlist.h>
+#include <qrect.h>
+#include <qsize.h>
+#include <qpixmap.h>
+#include <qstyle.h>
+#include <qsizepolicy.h>
+
+
+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 <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_CUT_COMBOBOX_H_
+#define _K3B_CUT_COMBOBOX_H_
+
+#include <kcombobox.h>
+#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 <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 "k3bdevicecombobox.h"
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bcore.h>
+
+#include <klocale.h>
+
+#include <qmap.h>
+#include <qptrvector.h>
+
+
+class K3bDeviceComboBox::Private
+{
+public:
+ QMap<QString, int> deviceIndexMap;
+ QPtrVector<K3bDevice::Device> 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<K3bDevice::Device> 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<K3bDevice::Device>& list )
+{
+ for( QPtrListIterator<K3bDevice::Device> it( list );
+ it.current(); ++it )
+ addDevice( it.current() );
+}
+
+
+void K3bDeviceComboBox::refreshDevices( const QPtrList<K3bDevice::Device>& 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 <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_DEVICE_COMBO_BOX_H_
+#define _K3B_DEVICE_COMBO_BOX_H_
+
+#include <kcombobox.h>
+#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<K3bDevice::Device>& );
+ /**
+ * Clears the device combo and tries to keep the current selection
+ */
+ void refreshDevices( const QPtrList<K3bDevice::Device>& );
+ 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 <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 "k3bdevicehandler.h"
+#include <k3bprogressinfoevent.h>
+#include <k3bthread.h>
+#include <k3bdevice.h>
+#include <k3bcdtext.h>
+
+
+
+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<char*>(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 <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_DEVICE_HANDLER_H_
+#define _K3B_DEVICE_HANDLER_H_
+
+#include <k3bthreadjob.h>
+#include "k3bdevice.h"
+#include "k3bdiskinfo.h"
+#include "k3bmsf.h"
+#include "k3bcdtext.h"
+#include "k3b_export.h"
+#include <qcstring.h>
+
+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 <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 "k3bdeviceselectiondialog.h"
+#include <k3bdevice.h>
+#include <k3bdevicecombobox.h>
+#include <k3bcore.h>
+#include <k3bdevicemanager.h>
+
+#include <qcombobox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qstring.h>
+#include <qframe.h>
+
+#include <klocale.h>
+
+
+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<K3bDevice::Device>& 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<K3bDevice::Device>& 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 <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_DEVICE_SELECTION_DIALOG_H
+#define K3B_DEVICE_SELECTION_DIALOG_H
+
+
+#include <kdialogbase.h>
+#include "k3b_export.h"
+#include <qptrlist.h>
+
+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<K3bDevice::Device>& );
+
+ 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<K3bDevice::Device>& 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 <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 "k3bdirsizejob.h"
+
+#include <k3bthread.h>
+#include <k3bthreadjob.h>
+#include <k3bsimplejobhandler.h>
+#include <k3bglobals.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+
+#include <qfileinfo.h>
+#include <qdir.h>
+
+
+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 <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_DIR_SIZE_JOB_H_
+#define _K3B_DIR_SIZE_JOB_H_
+
+#include <k3bthreadjob.h>
+#include <kio/global.h>
+
+#include <k3b_export.h>
+
+/**
+ * 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 <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 "k3bexceptions.h"
+#include <k3bdevice.h>
+
+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 <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_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 <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 "k3bfilesplitter.h"
+#include "k3bfilesysteminfo.h"
+
+#include <kdebug.h>
+
+#include <qfile.h>
+
+
+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 <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_FILE_SPLITTER_H_
+#define _K3B_FILE_SPLITTER_H_
+
+#include <qiodevice.h>
+#include <qstring.h>
+
+#include <kio/global.h>
+
+#include <k3b_export.h>
+
+
+/**
+ * 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:
+ *
+ * <pre>
+ * filename.iso
+ * filename.iso.001
+ * filename.iso.002
+ * ...
+ * </pre>
+ */
+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 <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 <config.h>
+
+#include "k3bfilesysteminfo.h"
+
+#include <k3bglobals.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+
+#include <kdebug.h>
+
+#ifdef Q_OS_FREEBSD
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h>
+# if defined(Q_OS_NETBSD)
+# include <sys/param.h>
+# if __NetBSD_Version__ > 299000000
+# define statfs statvfs
+# define f_type f_fsid
+# endif
+# endif
+#endif
+#ifdef HAVE_SYS_VFS_H
+# include <sys/vfs.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+
+
+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 <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_FILE_SYSTEM_INFO_H_
+#define _K3B_FILE_SYSTEM_INFO_H_
+
+#include <k3b_export.h>
+
+#include <qstring.h>
+
+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 <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 "k3bintmapcombobox.h"
+
+#include <qwhatsthis.h>
+#include <qmap.h>
+#include <qvaluevector.h>
+
+
+class K3bIntMapComboBox::Private
+{
+public:
+ QMap<int, int> valueIndexMap;
+ QMap<int, QPair<int, QString> > 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<int, QString>( 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 += "<p><b>" + KComboBox::text( i ) + "</b><br>";
+ ws += d->indexValueDescriptionMap[i].second;
+ }
+ ws += "<p>" + 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 <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_INT_MAP_COMBOBOX_H_
+#define _K3B_INT_MAP_COMBOBOX_H_
+
+#include <kcombobox.h>
+
+#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 <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 <qwidget.h>
+#include <qstring.h>
+
+#include "k3bintvalidator.h"
+
+#include <klocale.h>
+#include <kglobal.h>
+#include <kdebug.h>
+
+
+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 <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_INT_VALIDATOR_H_
+#define _K3B_INT_VALIDATOR_H_
+
+#include <qvalidator.h>
+#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 <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 <config.h>
+#include <k3bglobals.h>
+
+#include "k3biso9660.h"
+#include "k3biso9660backend.h"
+
+#include <k3bdevice.h>
+
+#include "libisofs/isofs.h"
+
+#include <qcstring.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qptrlist.h>
+
+#include <kdebug.h>
+
+
+/* callback function for libisofs */
+int K3bIso9660::read_callback( char* buf, sector_t start, int len, void* udata )
+{
+ K3bIso9660* isoF = static_cast<K3bIso9660*>(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<K3bIso9660*> (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<K3bIso9660File*>(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<K3bIso9660Directory*>(this)->expand();
+
+ QStringList l;
+
+ QDictIterator<K3bIso9660Entry> 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<K3bIso9660Directory*>(this)->expand();
+
+ QStringList l;
+
+ QDictIterator<K3bIso9660Entry> 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<K3bIso9660Directory*>(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<K3bIso9660Directory*>(e)->iso9660Entry( right );
+ }
+
+ return m_iso9660Entries[ name ];
+}
+
+
+const K3bIso9660Entry* K3bIso9660Directory::entry( const QString& name ) const
+{
+ return const_cast<K3bIso9660Directory*>(this)->entry( name );
+}
+
+
+const K3bIso9660Entry* K3bIso9660Directory::iso9660Entry( const QString& name ) const
+{
+ return const_cast<K3bIso9660Directory*>(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<K3bIso9660Directory> elToritoDirs;
+ QPtrList<K3bIso9660Directory> jolietDirs;
+ QPtrList<K3bIso9660Directory> isoDirs;
+ QPtrList<K3bIso9660Directory> 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<const K3bIso9660Directory*>(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 <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_ISO9660_H_
+#define _K3B_ISO9660_H_
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <qdatetime.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdict.h>
+
+#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<K3bIso9660Entry> m_entries;
+ QDict<K3bIso9660Entry> 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 <gyurco@users.sourceforge.net>.
+ * 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 <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 "k3biso9660backend.h"
+#include "k3blibdvdcss.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <qfile.h>
+
+#include <k3bdevice.h>
+
+
+//
+// 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<unsigned long long>(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<void*>(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 <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_ISO9660_BACKEND_H_
+#define _K3B_ISO9660_BACKEND_H_
+
+#include <qstring.h>
+
+#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 <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 <config.h>
+
+#include "k3blibdvdcss.h"
+
+#include <k3bdevice.h>
+#include <k3biso9660.h>
+#include <k3biso9660backend.h>
+
+#include <qfile.h>
+#include <qcstring.h>
+#include <qvaluevector.h>
+#include <qpair.h>
+
+#include <dlfcn.h>
+
+
+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<int,int> > 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<char*>( 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<const K3bIso9660File*>( 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<int,int> p;
+ int vob = 1;
+ for( ; vob < 100; ++vob ) {
+ filename.sprintf( "VIDEO_TS/VTS_%02d_%d.VOB", title, vob );
+ file = dynamic_cast<const K3bIso9660File*>( 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 <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_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 <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 "k3blistview.h"
+
+#include "k3bmsfedit.h"
+
+#include <qstringlist.h>
+#include <qfontmetrics.h>
+#include <qpainter.h>
+#include <qheader.h>
+#include <qrect.h>
+#include <qpushbutton.h>
+#include <qiconset.h>
+#include <qcombobox.h>
+#include <qspinbox.h>
+#include <qlineedit.h>
+#include <qlistbox.h>
+#include <qevent.h>
+#include <qvalidator.h>
+#include <qfont.h>
+#include <qpalette.h>
+#include <qstyle.h>
+#include <qapplication.h>
+#include <qprogressbar.h>
+#include <qimage.h>
+
+#include <kpixmapeffect.h>
+
+#include <limits.h>
+
+
+
+// ///////////////////////////////////////////////
+//
+// 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<K3bListView*>(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<K3bListView*>(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<QLineEdit*>( 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<QLineEdit*>( 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<K3bListViewItem*>( 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<QKeyEvent*>(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<K3bListViewItem*>( 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<K3bListViewItem*>( 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<QMouseEvent*>( e );
+ QListViewItem* item = itemAt( me->pos() );
+ int col = header()->sectionAt( me->pos().x() );
+ if( K3bCheckListViewItem* ci = dynamic_cast<K3bCheckListViewItem*>( 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<K3bListViewItem*>(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<QListViewItem>& 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<QListViewItem> 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 <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 K3BLISTVIEW_H
+#define K3BLISTVIEW_H
+
+
+#include <klistview.h>
+#include "k3b_export.h"
+#include <qptrvector.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <kpixmap.h>
+
+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<QListViewItem>& 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 <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 "k3blistviewitemanimator.h"
+
+#include <qtimer.h>
+#include <qlistview.h>
+
+#include <kpixmap.h>
+#include <kpixmapeffect.h>
+
+
+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 <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_LISTVIEWITEM_ANIMATOR_H_
+#define _K3B_LISTVIEWITEM_ANIMATOR_H_
+
+#include <qobject.h>
+#include <qpixmap.h>
+#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 <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 "k3bmd5job.h"
+#include <k3biso9660.h>
+#include <k3bglobals.h>
+#include <k3bdevice.h>
+#include <k3bfilesplitter.h>
+
+#include <kmdcodec.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kio/netaccess.h>
+
+#include <qtimer.h>
+#include <qcstring.h>
+#include <qsocketnotifier.h>
+
+#include <unistd.h>
+
+
+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<unsigned char*>(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 <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_MD5_JOB_H_
+#define _K3B_MD5_JOB_H_
+
+#include <k3bjob.h>
+#include <qcstring.h>
+#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 <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 "k3bmsfedit.h"
+#include "k3bglobals.h"
+
+#include <qstringlist.h>
+#include <qlineedit.h>
+#include <qstyle.h>
+#include <qfontmetrics.h>
+#include <qapplication.h>
+
+
+
+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 <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_MSF_EDIT_H
+#define K3B_MSF_EDIT_H
+
+
+#include <qspinbox.h>
+#include <qstring.h>
+#include <qvalidator.h>
+
+#include <k3bmsf.h>
+#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 <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 "k3bmultichoicedialog.h"
+#include "k3bstdguiitems.h"
+#include <k3brichtextlabel.h>
+
+#include <kpushbutton.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+
+#include <qlayout.h>
+#include <qsignalmapper.h>
+#include <qptrlist.h>
+#include <qlabel.h>
+#include <qhbox.h>
+#include <qmessagebox.h>
+
+
+class K3bMultiChoiceDialog::Private
+{
+public:
+ Private()
+ : mapper(0),
+ buttonLayout(0) {
+ }
+
+ QSignalMapper* mapper;
+ QPtrList<KPushButton> 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 <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_MULTI_CHOICE_DIALOG_H_
+#define _K3B_MULTI_CHOICE_DIALOG_H_
+
+#include <kdialog.h>
+#include <kstdguiitem.h>
+#include "k3b_export.h"
+
+#include <qmessagebox.h>
+
+
+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 <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 "k3bpipe.h"
+
+#include <kdebug.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+
+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 <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_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 <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 "k3bprogressdialog.h"
+
+#include <k3bbusywidget.h>
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qframe.h>
+#include <qwidgetstack.h>
+
+#include <klocale.h>
+#include <kprogress.h>
+
+
+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 <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_PROGRESS_DIALOG_H_
+#define _K3B_PROGRESS_DIALOG_H_
+
+#include <kdialogbase.h>
+#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 <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 "k3bpushbutton.h"
+
+#include <qtimer.h>
+#include <qpopupmenu.h>
+#include <qevent.h>
+
+#include <kglobalsettings.h>
+#include <kapplication.h>
+
+
+
+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<K3bPushButton*>(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<QMouseEvent*>(ev);
+ d->mousePressPos = mev->pos();
+ d->popupTimer->start( QApplication::startDragTime() );
+ }
+ else if( ev->type() == QEvent::MouseMove ) {
+ QMouseEvent* mev = static_cast<QMouseEvent*>(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 <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_PUSH_BUTTON_H_
+#define _K3B_PUSH_BUTTON_H_
+
+
+#include <kpushbutton.h>
+#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 <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 "k3bradioaction.h"
+
+#include <ktoolbarbutton.h>
+
+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<const KToolBarButton *>( senderObj ) )
+ return;
+
+ const_cast<KToolBarButton *>( static_cast<const KToolBarButton *>( 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 <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_RADIO_ACTION_H_
+#define _K3B_RADIO_ACTION_H_
+
+#include <kactionclasses.h>
+#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 <bastian@kde.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 "k3brichtextlabel.h"
+
+#include <qtooltip.h>
+#include <qstylesheet.h>
+#include <qsimplerichtext.h>
+
+#include <kglobalsettings.h>
+
+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 <bastian@kde.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 K3BRICHTEXTLABEL_H
+#define K3BRICHTEXTLABEL_H
+
+#include <qlabel.h>
+
+#include <k3b_export.h>
+
+/**
+ * @short A replacement for QLabel that supports richtext and proper layout management
+ *
+ * @author Waldo Bastian <bastian@kde.org>
+ */
+
+/*
+ * 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 <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 "k3bsignalwaiter.h"
+#include "k3bjob.h"
+
+#include <qeventloop.h>
+#include <qapplication.h>
+
+
+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 <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_SIGNAL_WAITER_H_
+#define _K3B_SIGNAL_WAITER_H_
+
+#include <qobject.h>
+
+#include <k3b_export.h>
+
+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 <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 "k3bstdguiitems.h"
+
+#include <qcheckbox.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qcombobox.h>
+#include <qframe.h>
+#include <qpalette.h>
+
+#include <klocale.h>
+
+
+QCheckBox* K3bStdGuiItems::simulateCheckbox( QWidget* parent, const char* name )
+{
+ QCheckBox* c = new QCheckBox( i18n("Simulate"), parent, name );
+ QWhatsThis::add( c, i18n("<p>If this option is checked K3b will perform all writing steps with the "
+ "laser turned off."
+ "<p>This is useful, for example, to test a higher writing speed "
+ "or whether your system is able to write on-the-fly."
+ "<p><b>Caution:</b> 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("<p>If this option is checked, K3b will write the CD in 'disk at once' mode as "
+ "compared to 'track at once' (TAO)."
+ "<p>It is always recommended to use DAO where possible."
+ "<p><b>Caution:</b> 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("<p>If this option is checked, K3b enables <em>Burnfree</em> "
+ "(or <em>Just Link</em>). This is "
+ "a feature of the CD writer which avoids buffer underruns."
+ "<p>Without <em>burnfree</em>, 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."
+ "<p>With <em>burnfree</em> the writer can <em>mark</em> 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, <b>it is "
+ "highly recommended to always choose an appropriate writing "
+ "speed to prevent the usage of burnfree, especially for audio CDs</b> "
+ "(in the worst case one would hear the gap)."
+ "<p><em>Burnfree</em> was formerly known as <em>Burnproof</em>, "
+ "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("<p>If this option is checked, K3b will only create an "
+ "image and not do any actual writing."
+ "<p>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("<p>If this option is checked, K3b will create an image before writing "
+ "the files to the CD/DVD. Otherwise the data will be written <em>on-the-fly</em>, "
+ "i.e. no intermediate image will be created."
+ "<p><b>Caution:</b> Although writing on-the-fly should work on most systems, make sure "
+ "the data is sent to the writer fast enough.")
+ + i18n("<p>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("<p>If this option is checked, K3b will remove any created images after the "
+ "writing has finished."
+ "<p>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("<p>If this option is checked, K3b will not create an image first but write "
+ "the files directly to the CD/DVD."
+ "<p><b>Caution:</b> Although this should work on most systems, make sure "
+ "the data is sent to the writer fast enough.")
+ + i18n("<p>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("<p>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."
+ "<p>CD-TEXT is an extension to the audio CD standard introduced by Sony."
+ "<p>CD-TEXT will only be usable on CD players that support this extension "
+ "(mostly car CD players)."
+ "<p>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("<p>Sets the correction mode for digital audio extraction."
+ "<ul><li>0: No checking, data is copied directly from the drive. "
+ "<li>1: Perform overlapped reading to avoid jitter.</li>"
+ "<li>2: Like 1 but with additional checks of the read audio data.</li>"
+ "<li>3: Like 2 but with additional scratch detection and repair.</li></ul>"
+ "<p><b>The extraction speed reduces from 0 to 3.</b>") );
+ 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("<p>If this option is checked K3b will not close the CD, and will write "
+ "a temporary table of contents.</p>"
+ "<p>This allows further sessions to be appended to the CD later.</p>") );
+ 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("<p>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."
+ "<p><b>Be aware that K3b currently does not support normalizing when writing "
+ "on the fly.</b>") );
+ 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("<p>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("<p>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."
+ "<p>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 <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_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 <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 "k3bstringutils.h"
+
+#include <qfontmetrics.h>
+
+#include <kdebug.h>
+
+
+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 <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_STRING_UTILS_H_
+#define _K3B_STRING_UTILS_H_
+
+#include <qstring.h>
+
+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 <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 "k3btempfile.h"
+
+#include <kglobal.h>
+#include <kstandarddirs.h>
+
+
+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 <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_TEMP_FILE_H_
+#define _K3B_TEMP_FILE_H_
+
+#include <ktempfile.h>
+
+#include <k3b_export.h>
+
+/**
+ * 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 <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 "k3bthreadwidget.h"
+#include "k3bdeviceselectiondialog.h"
+#include <k3bdevice.h>
+
+#include <qevent.h>
+#include <qapplication.h>
+#include <qwaitcondition.h>
+
+
+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<K3bDevice::Device*>( 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<DeviceSelectionEvent*>(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<void*>( 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 <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_THREAD_WIDGET_H_
+#define _K3B_THREAD_WIDGET_H_
+
+#include <qobject.h>
+#include <qintdict.h>
+
+
+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<Data> 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 <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 "k3bthroughputestimator.h"
+
+#include <qdatetime.h>
+#include <kdebug.h>
+
+
+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 <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_THROUGHPUT_ESTIMATOR_H_
+#define _K3B_THROUGHPUT_ESTIMATOR_H_
+
+#include <qobject.h>
+
+
+/**
+ * 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 <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 "k3btitlelabel.h"
+
+#include <k3bstringutils.h>
+
+#include <qpainter.h>
+#include <qevent.h>
+#include <qfontmetrics.h>
+#include <qfont.h>
+#include <qtooltip.h>
+
+
+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 <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_TITLE_LABEL_H_
+#define _K3B_TITLE_LABEL_H_
+
+#include <qframe.h>
+#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 <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 "k3btoolbox.h"
+
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <ktoolbarbutton.h>
+#include <kiconloader.h>
+
+#include <qtoolbutton.h>
+#include <qsizepolicy.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qtooltip.h>
+#include <qlabel.h>
+#include <qvbox.h>
+#include <qstyle.h>
+#include <qpainter.h>
+#include <qevent.h>
+#include <qobjectlist.h>
+
+
+/**
+ * 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<KToggleAction*>( 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<KActionMenu*>( 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<QWidget> 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 <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_TOOLBOX_H
+#define K3B_TOOLBOX_H
+
+#include <qframe.h>
+#include <qstring.h>
+#include <qtoolbutton.h>
+#include <qptrlist.h>
+#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<QWidget> 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 <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 "k3btoolbutton.h"
+
+#include <qstyle.h>
+#include <qpainter.h>
+#include <qevent.h>
+
+#include <kglobalsettings.h>
+#include <kapplication.h>
+
+
+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<K3bToolButton*>(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<QMouseEvent*>(ev);
+
+ if( d->instantMenu ) {
+ setDown(true);
+ openPopup();
+ return true;
+ }
+ else {
+ d->mousePressPos = mev->pos();
+ }
+ }
+ else if( ev->type() == QEvent::MouseMove ) {
+ QMouseEvent* mev = static_cast<QMouseEvent*>(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 <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_TOOL_BUTTON_H_
+#define _K3B_TOOL_BUTTON_H_
+
+#include "k3b_export.h"
+
+#include <qtoolbutton.h>
+
+class QPainter;
+class QEvent;
+
+
+/**
+ * the K3bToolButton is an enhanced QToolButton which adds two functionalities:
+ * <li>A delayed popup menu is shown immiadetely once the mouse is dragged downwards
+ * much like the KToolBarButton
+ * <li>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 <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 "k3bvalidators.h"
+
+#include <ctype.h>
+
+
+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 <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_VALIDATORS_H_
+#define _K3B_VALIDATORS_H_
+
+#include <qvalidator.h>
+#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:
+ * <ul>
+ * <li>C: country code (upper case letters or digits)</li>
+ * <li>O: owner code (upper case letters or digits)</li>
+ * <li>Y: year (digits)</li>
+ * <li>S: serial number (digits)</li>
+ * </ul>
+ */
+ 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 <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 "k3bwavefilewriter.h"
+#include <kdebug.h>
+
+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 <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 K3BWAVEFILEWRITER_H
+#define K3BWAVEFILEWRITER_H
+
+#include <qstring.h>
+#include <qfile.h>
+#include <qdatastream.h>
+#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 <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 "kcutlabel.h"
+
+#include <k3bstringutils.h>
+
+#include <qtooltip.h>
+#include <qstringlist.h>
+#include <kdebug.h>
+
+
+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 <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 KCUTLABEL_H
+#define KCUTLABEL_H
+
+#include <qlabel.h>
+#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 <gyurco@users.sourceforge.net>
+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 <byteswap.h>
+#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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 (i<n && s[i]) i++;
+ i++;
+ if (*d) i+=(strlen(*d)+1);
+ c=(char*) malloc(i);
+ if (!c) return -ENOMEM;
+ if (*d) {
+ strcpy(c,*d);
+ strncat(c,s,n);
+
+ free(*d);
+ } else
+ strncpy(c,s,n);
+ c[i-1]=0;
+ *d=c;
+ return 0;
+}
+
+static int str_append(char **d, const char *s) {
+ int i;
+ char *c;
+
+ i=strlen(s)+1;
+ if (*d) i+=(strlen(*d)+1);
+ c=(char*) malloc(i);
+ if (!c) return -ENOMEM;
+ if (*d) {
+ strcpy(c,*d);
+ strcat(c,s);
+ free(*d);
+ } else
+ strcpy(c,s);
+ c[i-1]=0;
+ *d=c;
+ return 0;
+}
+
+#define rrtlen(c) (((unsigned char) c & 0x80) ? 17 : 7)
+#define rrctime(f,c) ((unsigned char) f & 0x80) ? isodate_84261(c,0) : isodate_915(c,0)
+/**
+ * Parses the System Use area and fills rr_entry with values
+ */
+int ParseRR(struct iso_directory_record *idr, rr_entry *rrentry) {
+
+ int suspoffs,susplen,i,f,ret=0;
+ char *r, *c;
+ struct rock_ridge *rr;
+
+ suspoffs=33+isonum_711(idr->name_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 <time.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <iconv.h>
+
+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;i<num*5;i++) { printf(" "); };
+}
+
+void dumpflags(char flags) {
+ if (flags & 1) printf("HIDDEN ");
+ if (flags & 2) printf("DIR ");
+ if (flags & 4) printf("ASF ");
+}
+
+void dumpjoliet(char *c,int len) {
+
+ char outbuf[255];
+ size_t out;
+ int ret;
+ char *outptr;
+
+ outptr=(char*) &outbuf;
+ out=255;
+ if ((iconv(iconv_d,&c,&len,&outptr,&out))<0) {
+ printf("conversion error=%d",errno);
+ return;
+ }
+ ret=255-out;
+ dumpchars((char*) &outbuf,ret);
+}
+
+void dumpchardesc(char *c,int len) {
+
+ if (joliet)
+ dumpjoliet(c,len);
+ else {
+ dumpchars(c,len);
+ }
+}
+
+void dumpiso915time(char *t, int hs) {
+
+ time_t time;
+ char *c;
+
+ time=isodate_915(t,hs);
+ c=(char*) ctime(&time);
+ if (c && c[strlen(c)-1]==0x0a) c[strlen(c)-1]=0;
+ if (c) printf("%s",c);
+}
+
+void dumpiso84261time(char *t, int hs) {
+
+ time_t time;
+ char *c;
+
+ time=isodate_84261(t,hs);
+ c=(char*) ctime(&time);
+ if (c && c[strlen(c)-1]==0x0a) c[strlen(c)-1]=0;
+ if (c) printf("%s",c);
+}
+
+void dumpdirrec(struct iso_directory_record *dir) {
+
+ if (isonum_711(dir->name_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 <sys/time.h>
+
+#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 <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 __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS // needed for *_MAX macros in dvdread headers
+#endif
+
+#include "k3bvideodvd.h"
+
+#include <k3bdevice.h>
+
+#include <qfile.h>
+
+#include <klocale.h>
+
+#include <inttypes.h> // needed by dvdreads headers
+#include <dvdread/dvd_reader.h>
+#include <dvdread/ifo_types.h>
+#include <dvdread/ifo_read.h>
+
+
+// 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 <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_VIDEOVD_H_
+#define _K3B_VIDEOVD_H_
+
+#include <k3bvideodvdtitle.h>
+
+#include <k3b_export.h>
+
+#include <qstring.h>
+#include <qvaluevector.h>
+
+
+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<Title> 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