Merge lp:~mixxxcontributors/mixxx/features_autodj into lp:~mixxxdevelopers/mixxx/trunk

Proposed by RJ Skerry-Ryan
Status: Merged
Merged at revision: 2989
Proposed branch: lp:~mixxxcontributors/mixxx/features_autodj
Merge into: lp:~mixxxdevelopers/mixxx/trunk
Diff against target: 2584 lines (+1353/-475)
16 files modified
mixxx/res/images/autodj/bottom.svg (+137/-0)
mixxx/res/images/autodj/media-playlist-shuffle.svg (+214/-0)
mixxx/res/images/autodj/stock_mail-send-receive.svg (+87/-0)
mixxx/res/mixxx.qrc (+3/-0)
mixxx/src/dlgautodj.cpp (+487/-225)
mixxx/src/dlgautodj.h (+32/-9)
mixxx/src/dlgautodj.ui (+110/-18)
mixxx/src/library/autodjfeature.cpp (+33/-31)
mixxx/src/library/autodjfeature.h (+5/-3)
mixxx/src/library/browse/browsefeature.cpp (+94/-68)
mixxx/src/library/browse/browsefeature.h (+2/-2)
mixxx/src/library/browse/browsetablemodel.cpp (+108/-107)
mixxx/src/library/browse/browsetablemodel.h (+1/-1)
mixxx/src/library/dao/cratedao.h (+2/-0)
mixxx/src/widget/wtracktableview.cpp (+33/-8)
mixxx/src/widget/wtracktableview.h (+5/-3)
To merge this branch: bzr merge lp:~mixxxcontributors/mixxx/features_autodj
Reviewer Review Type Date Requested Status
RJ Skerry-Ryan Approve
Review via email: mp+96961@code.launchpad.net

Description of the change

This branch brings Daniel Schürmann improvements to AutoDJ into Mixxx. I have reviewed the branch and it looks good to me from a stability and product/feature point of view.

To post a comment you must log in.
Revision history for this message
RJ Skerry-Ryan (rryan) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'mixxx/res/images/autodj'
2=== added file 'mixxx/res/images/autodj/bottom.svg'
3--- mixxx/res/images/autodj/bottom.svg 1970-01-01 00:00:00 +0000
4+++ mixxx/res/images/autodj/bottom.svg 2012-03-12 04:06:20 +0000
5@@ -0,0 +1,137 @@
6+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
7+<!-- Created with Inkscape (http://www.inkscape.org/) -->
8+<svg
9+ xmlns:dc="http://purl.org/dc/elements/1.1/"
10+ xmlns:cc="http://creativecommons.org/ns#"
11+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
12+ xmlns:svg="http://www.w3.org/2000/svg"
13+ xmlns="http://www.w3.org/2000/svg"
14+ xmlns:xlink="http://www.w3.org/1999/xlink"
15+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
16+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
17+ width="48px"
18+ height="48px"
19+ id="svg4289"
20+ sodipodi:version="0.32"
21+ inkscape:version="0.46"
22+ sodipodi:docbase="/home/lapo/Icone/cvs/gnome-icon-theme/scalable/categories"
23+ sodipodi:docname="bottom.svg"
24+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
25+ <defs
26+ id="defs4291">
27+ <linearGradient
28+ id="linearGradient3155"
29+ inkscape:collect="always">
30+ <stop
31+ id="stop3157"
32+ offset="0"
33+ style="stop-color:#ffb584;stop-opacity:1;" />
34+ <stop
35+ id="stop3159"
36+ offset="1"
37+ style="stop-color:#ffb584;stop-opacity:0;" />
38+ </linearGradient>
39+ <linearGradient
40+ inkscape:collect="always"
41+ xlink:href="#linearGradient3155"
42+ id="linearGradient3273"
43+ gradientUnits="userSpaceOnUse"
44+ gradientTransform="matrix(0.1532521,0,0,0.1530054,-25.916429,-53.611392)"
45+ x1="325.71429"
46+ y1="369.50507"
47+ x2="325.71429"
48+ y2="546.64789" />
49+ </defs>
50+ <sodipodi:namedview
51+ id="base"
52+ pagecolor="#ffffff"
53+ bordercolor="#666"
54+ borderopacity="0.31372549"
55+ inkscape:pageopacity="0.0"
56+ inkscape:pageshadow="2"
57+ inkscape:zoom="5.656854"
58+ inkscape:cx="25.963489"
59+ inkscape:cy="20.551712"
60+ inkscape:current-layer="layer1"
61+ showgrid="true"
62+ inkscape:grid-bbox="true"
63+ inkscape:document-units="px"
64+ inkscape:window-width="1019"
65+ inkscape:window-height="732"
66+ inkscape:window-x="259"
67+ inkscape:window-y="19"
68+ inkscape:showpageshadow="false" />
69+ <metadata
70+ id="metadata4294">
71+ <rdf:RDF>
72+ <cc:Work
73+ rdf:about="">
74+ <dc:format>image/svg+xml</dc:format>
75+ <dc:type
76+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
77+ <dc:title>System Preferences</dc:title>
78+ <dc:creator>
79+ <cc:Agent>
80+ <dc:title>Andreas Nilsson</dc:title>
81+ </cc:Agent>
82+ </dc:creator>
83+ <dc:subject>
84+ <rdf:Bag>
85+ <rdf:li>category</rdf:li>
86+ <rdf:li>system</rdf:li>
87+ <rdf:li>preferences</rdf:li>
88+ <rdf:li>settings</rdf:li>
89+ <rdf:li>control center</rdf:li>
90+ </rdf:Bag>
91+ </dc:subject>
92+ <dc:contributor>
93+ <cc:Agent>
94+ <dc:title>Jakub Steiner</dc:title>
95+ </cc:Agent>
96+ </dc:contributor>
97+ <cc:license
98+ rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
99+ </cc:Work>
100+ <cc:License
101+ rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
102+ <cc:permits
103+ rdf:resource="http://web.resource.org/cc/Reproduction" />
104+ <cc:permits
105+ rdf:resource="http://web.resource.org/cc/Distribution" />
106+ <cc:requires
107+ rdf:resource="http://web.resource.org/cc/Notice" />
108+ <cc:permits
109+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
110+ <cc:requires
111+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
112+ <cc:requires
113+ rdf:resource="http://web.resource.org/cc/SourceCode" />
114+ </cc:License>
115+ </rdf:RDF>
116+ </metadata>
117+ <g
118+ id="layer1"
119+ inkscape:label="Layer 1"
120+ inkscape:groupmode="layer">
121+ <g
122+ id="g2453"
123+ inkscape:label="Calque 1"
124+ transform="matrix(0.1337942,0,0,0.1337942,-18.472238,-41.04701)" />
125+ <path
126+ style="fill:#ea5d00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.9139747;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
127+ d="M 6.7500156,19.774362 L 24.043348,39.555555 L 41.25,19.774362 L 33.004787,19.774362 L 33.004787,4.0000015 L 15.136157,4.0000015 L 15.136157,19.774362 L 6.7500156,19.774362 z"
128+ id="path4348"
129+ sodipodi:nodetypes="cccccccc" />
130+ <rect
131+ y="39.555557"
132+ x="6.75"
133+ height="4.4444442"
134+ width="34.499985"
135+ id="rect4242"
136+ style="fill:#ea5d00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.84845495;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
137+ <path
138+ style="fill:url(#linearGradient3273);fill-opacity:1"
139+ d="M 15.131549,4.0000015 L 15.131549,19.76389 L 6.75,19.76389 L 15.027214,29.208333 C 17.837762,29.718667 20.845017,30.041667 23.999992,30.041667 C 27.180083,30.041667 30.212896,29.726456 33.042326,29.208333 L 41.249983,19.76389 L 33.007548,19.76389 L 33.007548,4.0000015 L 15.131549,4.0000015 z"
140+ id="path3261" />
141+ </g>
142+</svg>
143
144=== added file 'mixxx/res/images/autodj/media-playlist-shuffle.svg'
145--- mixxx/res/images/autodj/media-playlist-shuffle.svg 1970-01-01 00:00:00 +0000
146+++ mixxx/res/images/autodj/media-playlist-shuffle.svg 2012-03-12 04:06:20 +0000
147@@ -0,0 +1,214 @@
148+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
149+<!-- Created with Inkscape (http://www.inkscape.org/) -->
150+
151+<svg
152+ xmlns:dc="http://purl.org/dc/elements/1.1/"
153+ xmlns:cc="http://creativecommons.org/ns#"
154+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
155+ xmlns:svg="http://www.w3.org/2000/svg"
156+ xmlns="http://www.w3.org/2000/svg"
157+ xmlns:xlink="http://www.w3.org/1999/xlink"
158+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
159+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
160+ width="48"
161+ height="48"
162+ id="svg7854"
163+ sodipodi:version="0.32"
164+ inkscape:version="0.47 r22583"
165+ version="1.0"
166+ sodipodi:docname="media-playlist-shuffle.svg"
167+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
168+ inkscape:export-filename="/home/lapo/Icone/gnome-icon-theme/32x32/status/media-playlist-repeat.png"
169+ inkscape:export-xdpi="90"
170+ inkscape:export-ydpi="90">
171+ <defs
172+ id="defs7856">
173+ <linearGradient
174+ gradientUnits="userSpaceOnUse"
175+ y2="21.132059"
176+ x2="22.892584"
177+ y1="0.90414524"
178+ x1="22.892584"
179+ id="linearGradient3178"
180+ xlink:href="#linearGradient3172"
181+ inkscape:collect="always" />
182+ <linearGradient
183+ id="linearGradient3172">
184+ <stop
185+ id="stop3174"
186+ offset="0"
187+ style="stop-color:#ffb584;stop-opacity:1;" />
188+ <stop
189+ id="stop3176"
190+ offset="1"
191+ style="stop-color:#ffb584;stop-opacity:0;" />
192+ </linearGradient>
193+ <linearGradient
194+ inkscape:collect="always"
195+ xlink:href="#linearGradient3172"
196+ id="linearGradient3747"
197+ gradientUnits="userSpaceOnUse"
198+ x1="22.892584"
199+ y1="0.90414524"
200+ x2="22.892584"
201+ y2="21.132059" />
202+ <linearGradient
203+ inkscape:collect="always"
204+ xlink:href="#linearGradient3172"
205+ id="linearGradient3752"
206+ gradientUnits="userSpaceOnUse"
207+ x1="22.892584"
208+ y1="0.90414524"
209+ x2="22.892584"
210+ y2="21.132059"
211+ gradientTransform="matrix(0.644962,0,0,-1.1832362,59.235153,43.983663)" />
212+ <linearGradient
213+ inkscape:collect="always"
214+ xlink:href="#linearGradient3172"
215+ id="linearGradient3755"
216+ gradientUnits="userSpaceOnUse"
217+ gradientTransform="matrix(0.644962,0,0,1.1832362,9.235153,4.016337)"
218+ x1="22.892584"
219+ y1="0.90414524"
220+ x2="22.892584"
221+ y2="21.132059" />
222+ </defs>
223+ <sodipodi:namedview
224+ id="base"
225+ pagecolor="#ffffff"
226+ bordercolor="#afafaf"
227+ borderopacity="1"
228+ gridtolerance="15.1"
229+ guidetolerance="10"
230+ objecttolerance="10"
231+ inkscape:pageopacity="0"
232+ inkscape:pageshadow="2"
233+ inkscape:zoom="8"
234+ inkscape:cx="20.022534"
235+ inkscape:cy="20.71947"
236+ inkscape:document-units="px"
237+ inkscape:current-layer="layer1"
238+ width="48px"
239+ height="48px"
240+ inkscape:showpageshadow="false"
241+ inkscape:window-width="872"
242+ inkscape:window-height="723"
243+ inkscape:window-x="406"
244+ inkscape:window-y="21"
245+ showgrid="false"
246+ inkscape:grid-points="false"
247+ showborder="true"
248+ showguides="false"
249+ inkscape:guide-bbox="false"
250+ inkscape:grid-bbox="true"
251+ inkscape:object-paths="false"
252+ inkscape:window-maximized="0">
253+ <sodipodi:guide
254+ orientation="horizontal"
255+ position="8.6620581"
256+ id="guide7377" />
257+ <sodipodi:guide
258+ orientation="horizontal"
259+ position="6"
260+ id="guide7379" />
261+ <sodipodi:guide
262+ orientation="horizontal"
263+ position="36.062446"
264+ id="guide7492" />
265+ <sodipodi:guide
266+ orientation="horizontal"
267+ position="51"
268+ id="guide7046" />
269+ <sodipodi:guide
270+ orientation="horizontal"
271+ position="-17.5"
272+ id="guide7233" />
273+ <sodipodi:guide
274+ orientation="horizontal"
275+ position="-29"
276+ id="guide7235" />
277+ <sodipodi:guide
278+ orientation="horizontal"
279+ position="44.547727"
280+ id="guide6795" />
281+ <sodipodi:guide
282+ orientation="horizontal"
283+ position="16.970563"
284+ id="guide6797" />
285+ <sodipodi:guide
286+ orientation="horizontal"
287+ position="23.511301"
288+ id="guide6914" />
289+ <inkscape:grid
290+ id="GridFromPre046Settings"
291+ type="xygrid"
292+ originx="0px"
293+ originy="0px"
294+ spacingx="0.5px"
295+ spacingy="0.5px"
296+ color="#0000ff"
297+ empcolor="#0000ff"
298+ opacity="0.2"
299+ empopacity="0.4"
300+ empspacing="2" />
301+ </sodipodi:namedview>
302+ <metadata
303+ id="metadata7859">
304+ <rdf:RDF>
305+ <cc:Work
306+ rdf:about="">
307+ <dc:format>image/svg+xml</dc:format>
308+ <dc:type
309+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
310+ <dc:creator>
311+ <cc:Agent>
312+ <dc:title>Lapo Calamandrei</dc:title>
313+ </cc:Agent>
314+ </dc:creator>
315+ <dc:source />
316+ <cc:license
317+ rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
318+ <dc:title></dc:title>
319+ <dc:subject>
320+ <rdf:Bag />
321+ </dc:subject>
322+ </cc:Work>
323+ <cc:License
324+ rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
325+ <cc:permits
326+ rdf:resource="http://web.resource.org/cc/Reproduction" />
327+ <cc:permits
328+ rdf:resource="http://web.resource.org/cc/Distribution" />
329+ <cc:requires
330+ rdf:resource="http://web.resource.org/cc/Notice" />
331+ <cc:permits
332+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
333+ <cc:requires
334+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
335+ <cc:requires
336+ rdf:resource="http://web.resource.org/cc/SourceCode" />
337+ </cc:License>
338+ </rdf:RDF>
339+ </metadata>
340+ <g
341+ inkscape:label="Layer 1"
342+ inkscape:groupmode="layer"
343+ id="layer1">
344+ <path
345+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#ea5d00;fill:#ea5d00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter"
346+ d="m 31.458167,11 0,0.971084 0,2.506024 -2.5498,0 c -2.309243,1e-6 -4.600856,0.959829 -6.438247,2.568675 -1.848702,1.618749 -3.250996,4.052721 -3.250996,6.954217 0,1.569915 -0.481869,2.684008 -1.211156,3.414458 -0.729287,0.73045 -1.72852,1.096385 -2.868526,1.096385 l -4.589641,0 -2.0398408,0 -0.5099602,0 0,0.501205 0,4.009639 0,0.501205 0.5099602,0 2.0398408,0 4.589641,0 c 4.913523,0 9.179283,-4.047685 9.179283,-9.522892 0,-1.311125 0.627138,-2.380239 1.593626,-3.226506 0.947549,-0.829685 2.290606,-1.284337 2.996016,-1.284337 l 2.5498,0 0,2.506024 0,0.971084 L 32.25498,22.40241 39.394422,17.390361 40,16.983133 39.394422,16.575904 32.25498,11.563855 31.458167,11 z M 8,14.477108 l 0,0.501205 0,4.009639 0,0.501205 0.5099602,0 2.0398408,0 4.589641,0 c 1.140006,0 2.139239,0.365935 2.868526,1.096385 0.383279,0.38389 0.711734,0.865992 0.924303,1.472289 0.409442,-1.928125 1.388391,-3.582339 2.645418,-4.855421 -0.0054,-0.0055 0.0055,-0.0258 0,-0.03133 -1.680631,-1.696317 -3.981485,-2.693972 -6.438247,-2.693972 l -4.589641,0 -2.0398408,0 -0.5099602,0 z m 23.458167,10.556627 0,0.971084 0,2.506024 -2.5498,0 c -0.70541,0 -2.048467,-0.454652 -2.996016,-1.284337 -0.528622,-0.462867 -0.932659,-0.998256 -1.211156,-1.59759 -0.308884,1.992948 -1.187966,3.74975 -2.422311,5.137349 0.06485,0.05987 0.125211,0.13014 0.191236,0.187952 1.837391,1.608846 4.129004,2.568674 6.438247,2.568675 l 2.5498,0 0,2.506024 0,0.971084 0.796813,-0.563855 7.139442,-5.012049 L 40,31.016867 39.394422,30.609639 32.25498,25.59759 31.458167,25.033735 z"
347+ id="path6784" />
348+ <path
349+ style="fill:url(#linearGradient3755);fill-opacity:1;stroke:none"
350+ d="m 24,29.65625 c -0.297307,0 -0.5803,-0.02559 -0.875,-0.03125 0.774683,-1.167911 1.33229,-2.514662 1.5625,-4 0.278497,0.599334 0.690128,1.130883 1.21875,1.59375 0.947549,0.829685 2.29459,1.28125 3,1.28125 l 2.5625,0 0,-2.5 0,-0.96875 0.78125,0.5625 3.46875,2.4375 C 32.250392,29.058149 28.258286,29.65625 24,29.65625 z M 22.5625,29.625 C 19.537058,29.52951 16.652999,29.1332 14.03125,28.5 l 1.09375,0 c 1.140006,0 2.145713,-0.3633 2.875,-1.09375 0.729287,-0.73045 1.21875,-1.836335 1.21875,-3.40625 0,-2.901496 1.401298,-5.350001 3.25,-6.96875 1.837391,-1.608846 4.128257,-2.562499 6.4375,-2.5625 l 2.5625,0 0,-2.5 0,-0.96875 0.78125,0.5625 7.15625,5 L 40,16.96875 39.40625,17.375 32.25,22.40625 l -0.78125,0.5625 0,-0.96875 0,-2.5 -2.5625,0 c -0.70541,0 -2.052451,0.451565 -3,1.28125 C 24.939762,21.627517 24.3125,22.688875 24.3125,24 c 0,2.153291 -0.650512,4.072677 -1.75,5.625 z m -3.625,-7.5625 C 18.724931,21.456203 18.383279,20.97764 18,20.59375 17.270713,19.8633 16.265006,19.5 15.125,19.5 l -4.5625,0 -2.0625,0 -0.5,0 0,-0.5 0,-4.03125 0,-0.5 0.5,0 2.0625,0 4.5625,0 c 2.456762,0 4.756869,0.991183 6.4375,2.6875 0.0055,0.0055 -0.0054,0.02575 0,0.03125 -1.257027,1.273082 -2.215558,2.946875 -2.625,4.875 z"
351+ id="path3741" />
352+ <g
353+ transform="matrix(0.1337942,0,0,-0.1337942,31.527762,89.04701)"
354+ inkscape:label="Calque 1"
355+ id="g3743" />
356+ <g
357+ transform="matrix(0.1672428,0,0,-0.1672428,38.442916,104.62323)"
358+ inkscape:label="Calque 1"
359+ id="g3745" />
360+ </g>
361+</svg>
362
363=== added file 'mixxx/res/images/autodj/stock_mail-send-receive.svg'
364--- mixxx/res/images/autodj/stock_mail-send-receive.svg 1970-01-01 00:00:00 +0000
365+++ mixxx/res/images/autodj/stock_mail-send-receive.svg 2012-03-12 04:06:20 +0000
366@@ -0,0 +1,87 @@
367+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
368+<!-- Created with Inkscape (http://www.inkscape.org/) -->
369+
370+<svg
371+ xmlns:dc="http://purl.org/dc/elements/1.1/"
372+ xmlns:cc="http://creativecommons.org/ns#"
373+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
374+ xmlns:svg="http://www.w3.org/2000/svg"
375+ xmlns="http://www.w3.org/2000/svg"
376+ xmlns:xlink="http://www.w3.org/1999/xlink"
377+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
378+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
379+ width="48px"
380+ height="48px"
381+ id="svg3787"
382+ version="1.1"
383+ inkscape:version="0.47 r22583"
384+ sodipodi:docname="Nouveau document 4">
385+ <defs
386+ id="defs3789">
387+ <linearGradient
388+ inkscape:collect="always"
389+ xlink:href="#linearGradient3172"
390+ id="linearGradient3767"
391+ gradientUnits="userSpaceOnUse"
392+ gradientTransform="matrix(0.644962,0,0,1.1832362,9.235153,4.016337)"
393+ x1="22.892584"
394+ y1="0.90414524"
395+ x2="22.892584"
396+ y2="21.132059" />
397+ <linearGradient
398+ id="linearGradient3172">
399+ <stop
400+ id="stop3174"
401+ offset="0"
402+ style="stop-color:#ffb584;stop-opacity:1;" />
403+ <stop
404+ id="stop3176"
405+ offset="1"
406+ style="stop-color:#ffb584;stop-opacity:0;" />
407+ </linearGradient>
408+ </defs>
409+ <sodipodi:namedview
410+ id="base"
411+ pagecolor="#ffffff"
412+ bordercolor="#666666"
413+ borderopacity="1.0"
414+ inkscape:pageopacity="0.0"
415+ inkscape:pageshadow="2"
416+ inkscape:zoom="7"
417+ inkscape:cx="24"
418+ inkscape:cy="24"
419+ inkscape:current-layer="layer1"
420+ showgrid="true"
421+ inkscape:grid-bbox="true"
422+ inkscape:document-units="px"
423+ inkscape:window-width="596"
424+ inkscape:window-height="502"
425+ inkscape:window-x="768"
426+ inkscape:window-y="24"
427+ inkscape:window-maximized="0" />
428+ <metadata
429+ id="metadata3792">
430+ <rdf:RDF>
431+ <cc:Work
432+ rdf:about="">
433+ <dc:format>image/svg+xml</dc:format>
434+ <dc:type
435+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
436+ <dc:title></dc:title>
437+ </cc:Work>
438+ </rdf:RDF>
439+ </metadata>
440+ <g
441+ id="layer1"
442+ inkscape:label="Layer 1"
443+ inkscape:groupmode="layer">
444+ <path
445+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#ea5d00;fill:#ea5d00;fill-opacity:1;stroke:none;stroke-width:0.99999988;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter"
446+ d="m 14.59375,4 -0.375,0.375 -9.46875,9.15625 -0.75,0.75 1.125,0 4.3125,0 0,18.03125 0,0.46875 0.53125,-0.03125 9.3125,-0.03125 0.5,0 0,-0.4375 0,-18 4.375,0 1.15625,0 -0.75,-0.75 L 14.96875,4.375 14.59375,4 z m 13.46875,11.21875 0,0.4375 0,18.0625 -4.25,0 -1.15625,0 0.75,0.75 L 32.875,43.625 33.25,44 l 0.40625,-0.375 9.5625,-9.15625 0.78125,-0.75 -1.15625,0 -4.40625,0 0,-18 0,-0.4375 -0.53125,0 -9.3125,-0.0625 -0.53125,0 z"
447+ id="path4360" />
448+ <path
449+ style="fill:url(#linearGradient3767);fill-opacity:1;stroke:none"
450+ d="M 19.78125,29.4375 C 15.932317,29.076763 12.418889,28.236656 9.4375,27.03125 l 0,-12.75 -4.3125,0 -1.125,0 0.75,-0.75 9.46875,-9.15625 0.375,-0.375 0.375,0.375 9.59375,9.15625 0.75,0.75 -1.15625,0 -4.375,0 0,15.15625 z m 8.28125,0 0,-13.78125 0,-0.4375 0.53125,0 9.3125,0.0625 0.53125,0 0,0.4375 0,11.34375 c -2.995811,1.195807 -6.517914,2.027067 -10.375,2.375 z"
451+ id="path3753" />
452+ </g>
453+</svg>
454
455=== modified file 'mixxx/res/mixxx.qrc'
456--- mixxx/res/mixxx.qrc 2011-12-22 18:43:09 +0000
457+++ mixxx/res/mixxx.qrc 2012-03-12 04:06:20 +0000
458@@ -1,5 +1,8 @@
459 <RCC>
460 <qresource prefix="/">
461+ <file>images/autodj/media-playlist-shuffle.svg</file>
462+ <file>images/autodj/stock_mail-send-receive.svg</file>
463+ <file>images/autodj/bottom.svg</file>
464 <file>html/crates.html</file>
465 <file>html/playlists.html</file>
466 <file>images/mixxx-icon.png</file>
467
468=== modified file 'mixxx/src/dlgautodj.cpp'
469--- mixxx/src/dlgautodj.cpp 2011-11-30 06:19:47 +0000
470+++ mixxx/src/dlgautodj.cpp 2012-03-12 04:06:20 +0000
471@@ -1,28 +1,38 @@
472 #include <QSqlTableModel>
473-#include "widget/wwidget.h"
474-#include "widget/wskincolor.h"
475-#include "widget/wtracktableview.h"
476+
477+#include "dlgautodj.h"
478+
479 #include "controlobject.h"
480 #include "controlobjectthreadmain.h"
481+#include "library/playlisttablemodel.h"
482 #include "library/trackcollection.h"
483-#include "library/playlisttablemodel.h"
484-#include "dlgautodj.h"
485+#include "playerinfo.h"
486+#include "widget/wskincolor.h"
487+#include "widget/wtracktableview.h"
488+#include "widget/wwidget.h"
489
490+#define CONFIG_KEY "[Auto DJ]"
491+const char* kTransitionPreferenceName = "Transition";
492+const int kTransitionPreferenceDefault = 10;
493
494 DlgAutoDJ::DlgAutoDJ(QWidget* parent, ConfigObject<ConfigValue>* pConfig,
495- TrackCollection* pTrackCollection, MixxxKeyboard* pKeyboard)
496- : QWidget(parent), Ui::DlgAutoDJ(), m_playlistDao(pTrackCollection->getPlaylistDAO())
497-{
498+ TrackCollection* pTrackCollection,
499+ MixxxKeyboard* pKeyboard)
500+ : QWidget(parent),
501+ Ui::DlgAutoDJ(),
502+ m_pConfig(pConfig),
503+ m_pTrackCollection(pTrackCollection),
504+ m_pTrackTableView(
505+ new WTrackTableView(this, pConfig, m_pTrackCollection)),
506+ m_playlistDao(pTrackCollection->getPlaylistDAO()),
507+ m_bAutoDJEnabled(false),
508+ m_bFadeNow(false),
509+ m_eState(ADJ_IDLE),
510+ m_posThreshold1(1.0f),
511+ m_posThreshold2(1.0f) {
512 setupUi(this);
513
514- m_pConfig = pConfig;
515- m_pTrackCollection = pTrackCollection;
516- m_bAutoDJEnabled = false;
517- m_bPlayer1Primed = false;
518- m_bPlayer2Primed = false;
519- m_pTrackTableView = new WTrackTableView(this, pConfig, m_pTrackCollection);
520 m_pTrackTableView->installEventFilter(pKeyboard);
521-
522 connect(m_pTrackTableView, SIGNAL(loadTrack(TrackPointer)),
523 this, SIGNAL(loadTrack(TrackPointer)));
524 connect(m_pTrackTableView, SIGNAL(loadTrackToPlayer(TrackPointer, QString)),
525@@ -34,8 +44,8 @@
526 m_pTrackTablePlaceholder->hide();
527 box->insertWidget(1, m_pTrackTableView);
528
529- m_pAutoDJTableModel = new PlaylistTableModel(this, pTrackCollection,
530- "mixxx.db.model.autodj");
531+ m_pAutoDJTableModel = new PlaylistTableModel(this, pTrackCollection,
532+ "mixxx.db.model.autodj");
533 int playlistId = m_playlistDao.getPlaylistIdFromName(AUTODJ_TABLE);
534 if (playlistId < 0) {
535 m_playlistDao.createPlaylist(AUTODJ_TABLE, true);
536@@ -44,7 +54,7 @@
537 m_pAutoDJTableModel->setPlaylist(playlistId);
538 m_pTrackTableView->loadTrackModel(m_pAutoDJTableModel);
539
540- //Override some playlist-view properties:
541+ // Override some playlist-view properties:
542
543 // Do not set this because it disables auto-scrolling
544 //m_pTrackTableView->setDragDropMode(QAbstractItemView::InternalMove);
545@@ -55,43 +65,65 @@
546 connect(pushButtonShuffle, SIGNAL(clicked(bool)),
547 this, SLOT(shufflePlaylist(bool)));
548
549+ connect(pushButtonSkipNext, SIGNAL(clicked(bool)),
550+ this, SLOT(skipNext(bool)));
551+
552+ connect(pushButtonFadeNow, SIGNAL(clicked(bool)),
553+ this, SLOT(fadeNow(bool)));
554+
555+ connect(spinBoxTransition, SIGNAL(valueChanged(int)),
556+ this, SLOT(transitionValueChanged(int)));
557+
558 connect(pushButtonAutoDJ, SIGNAL(toggled(bool)),
559 this, SLOT(toggleAutoDJ(bool))); _blah;
560
561+ // playposition is from -0.14 to + 1.14
562 m_pCOPlayPos1 = new ControlObjectThreadMain(
563- ControlObject::getControl(ConfigKey("[Channel1]", "playposition")));
564+ ControlObject::getControl(ConfigKey("[Channel1]", "playposition")));
565 m_pCOPlayPos2 = new ControlObjectThreadMain(
566- ControlObject::getControl(ConfigKey("[Channel2]", "playposition")));
567+ ControlObject::getControl(ConfigKey("[Channel2]", "playposition")));
568 m_pCOPlay1 = new ControlObjectThreadMain(
569- ControlObject::getControl(ConfigKey("[Channel1]", "play")));
570+ ControlObject::getControl(ConfigKey("[Channel1]", "play")));
571 m_pCOPlay2 = new ControlObjectThreadMain(
572- ControlObject::getControl(ConfigKey("[Channel2]", "play")));
573+ ControlObject::getControl(ConfigKey("[Channel2]", "play")));
574+ m_pCOPlay1Fb = new ControlObjectThreadMain(
575+ ControlObject::getControl(ConfigKey("[Channel1]", "play")));
576+ m_pCOPlay2Fb = new ControlObjectThreadMain(
577+ ControlObject::getControl(ConfigKey("[Channel2]", "play")));
578 m_pCORepeat1 = new ControlObjectThreadMain(
579- ControlObject::getControl(ConfigKey("[Channel1]", "repeat")));
580+ ControlObject::getControl(ConfigKey("[Channel1]", "repeat")));
581 m_pCORepeat2 = new ControlObjectThreadMain(
582- ControlObject::getControl(ConfigKey("[Channel2]", "repeat")));
583+ ControlObject::getControl(ConfigKey("[Channel2]", "repeat")));
584 m_pCOCrossfader = new ControlObjectThreadMain(
585- ControlObject::getControl(ConfigKey("[Master]", "crossfader")));
586+ ControlObject::getControl(ConfigKey("[Master]", "crossfader")));
587+
588+ QString str_autoDjTransition = m_pConfig->getValueString(
589+ ConfigKey(CONFIG_KEY, kTransitionPreferenceName));
590+ if (str_autoDjTransition.isEmpty()) {
591+ spinBoxTransition->setValue(kTransitionPreferenceDefault);
592+ } else {
593+ spinBoxTransition->setValue(str_autoDjTransition.toInt());
594+ }
595 }
596
597-DlgAutoDJ::~DlgAutoDJ()
598-{
599+DlgAutoDJ::~DlgAutoDJ() {
600 delete m_pCOPlayPos1;
601 delete m_pCOPlayPos2;
602 delete m_pCOPlay1;
603 delete m_pCOPlay2;
604+ delete m_pCOPlay1Fb;
605+ delete m_pCOPlay2Fb;
606+ delete m_pCORepeat1;
607 delete m_pCORepeat2;
608 delete m_pCOCrossfader;
609+ delete m_pAutoDJTableModel;
610 }
611
612-void DlgAutoDJ::onShow()
613-{
614+void DlgAutoDJ::onShow() {
615 m_pAutoDJTableModel->select();
616 }
617
618-void DlgAutoDJ::setup(QDomNode node)
619-{
620-
621+void DlgAutoDJ::setup(QDomNode node) {
622 QPalette pal = palette();
623
624 // Row colors
625@@ -108,9 +140,6 @@
626 // the future this should be configurable from the skin with this as the
627 // fallback option
628 QColor text(255 - r1.red(), 255 - r1.green(), 255 - r1.blue());
629-
630- //setAlternatingRowColors ( true );
631-
632 QColor fgColor;
633 fgColor.setNamedColor(WWidget::selectNodeQString(node, "FgColor"));
634 fgColor = WSkinColor::getCorrectColor(fgColor);
635@@ -119,26 +148,24 @@
636 pal.setColor(QPalette::AlternateBase, r2);
637 pal.setColor(QPalette::Text, text);
638 pal.setColor(QPalette::WindowText, fgColor);
639-
640 }
641
642 setPalette(pal);
643
644 pushButtonAutoDJ->setPalette(pal);
645- //m_pTrackTableView->setPalette(pal); //Since we're getting this passed into us already created,
646- //shouldn't need to set the palette.
647-}
648-
649-void DlgAutoDJ::onSearchStarting()
650-{
651-}
652-
653-void DlgAutoDJ::onSearchCleared()
654-{
655-}
656-
657-void DlgAutoDJ::onSearch(const QString& text)
658-{
659+
660+ // Since we're getting this passed into us already created, shouldn't need
661+ // to set the palette.
662+ //m_pTrackTableView->setPalette(pal);
663+}
664+
665+void DlgAutoDJ::onSearchStarting() {
666+}
667+
668+void DlgAutoDJ::onSearchCleared() {
669+}
670+
671+void DlgAutoDJ::onSearch(const QString& text) {
672 m_pAutoDJTableModel->search(text);
673 }
674
675@@ -154,204 +181,439 @@
676 m_pTrackTableView->moveSelection(delta);
677 }
678
679-void DlgAutoDJ::shufflePlaylist(bool buttonChecked)
680-{
681+void DlgAutoDJ::shufflePlaylist(bool buttonChecked) {
682 Q_UNUSED(buttonChecked);
683 qDebug() << "Shuffling AutoDJ playlist";
684 m_pAutoDJTableModel->shuffleTracks(m_pAutoDJTableModel->index(0, 0));
685 qDebug() << "Shuffling done";
686 }
687
688-void DlgAutoDJ::toggleAutoDJ(bool toggle)
689-{
690- if (toggle) //Enable Auto DJ
691- {
692- if (m_pCOPlay1->get() == 1.0f && m_pCOPlay2->get() == 1.0f) {
693+void DlgAutoDJ::skipNext(bool buttonChecked) {
694+ Q_UNUSED(buttonChecked);
695+ qDebug() << "Skip Next";
696+ // Load the next song from the queue.
697+ if (m_pCOPlay1Fb->get() == 0.0f) {
698+ removePlayingTrackFromQueue("[Channel1]");
699+ loadNextTrackFromQueue();
700+ } else if (m_pCOPlay2Fb->get() == 0.0f) {
701+ removePlayingTrackFromQueue("[Channel2]");
702+ loadNextTrackFromQueue();
703+ }
704+}
705+
706+void DlgAutoDJ::fadeNow(bool buttonChecked) {
707+ Q_UNUSED(buttonChecked);
708+ qDebug() << "Fade Now";
709+ if (m_eState == ADJ_IDLE && m_bAutoDJEnabled) {
710+ m_bFadeNow = true;
711+ double crossfader = m_pCOCrossfader->get();
712+ if (crossfader <= 0.3f && m_pCOPlay1Fb->get() == 1.0f) {
713+ m_posThreshold1 = m_pCOPlayPos1->get() -
714+ ((crossfader + 1.0f) / 2 * (m_fadeDuration1));
715+ // Repeat is disabled by FadeNow but disables auto Fade
716+ m_pCORepeat1->slotSet(0.0f);
717+ } else if (crossfader >= -0.3f && m_pCOPlay2Fb->get() == 1.0f) {
718+ m_posThreshold2 = m_pCOPlayPos2->get() -
719+ ((1.0f - crossfader) / 2 * (m_fadeDuration2));
720+ // Repeat is disabled by FadeNow but disables auto Fade
721+ m_pCORepeat2->slotSet(0.0f);
722+ }
723+ }
724+}
725+
726+void DlgAutoDJ::toggleAutoDJ(bool toggle) {
727+ bool deck1Playing = m_pCOPlay1Fb->get() == 1.0f;
728+ bool deck2Playing = m_pCOPlay2Fb->get() == 1.0f;
729+
730+ if (toggle) { // Enable Auto DJ
731+ if (deck1Playing && deck2Playing) {
732+ QMessageBox::warning(
733+ NULL, tr("Auto-DJ"),
734+ tr("One player must be stopped to enable Auto-DJ mode."),
735+ QMessageBox::Ok);
736 qDebug() << "One player must be stopped before enabling Auto DJ mode";
737 pushButtonAutoDJ->setChecked(false);
738 return;
739 }
740
741+ // Never load the same track if it is already playing
742+ if (deck1Playing) {
743+ removePlayingTrackFromQueue("[Channel1]");
744+ }
745+ if (deck2Playing) {
746+ removePlayingTrackFromQueue("[Channel2]");
747+ }
748+
749+ TrackPointer nextTrack = getNextTrackFromQueue();
750+ if (!nextTrack) {
751+ qDebug() << "Queue is empty now";
752+ pushButtonAutoDJ->setChecked(false);
753+ return;
754+ }
755+
756+ // Track is available so GO
757+ pushButtonAutoDJ->setToolTip(tr("Disable Auto DJ"));
758 pushButtonAutoDJ->setText(tr("Disable Auto DJ"));
759+ qDebug() << "Auto DJ enabled";
760 m_bAutoDJEnabled = true;
761+
762 connect(m_pCOPlayPos1, SIGNAL(valueChanged(double)),
763- this, SLOT(player1PositionChanged(double)));
764+ this, SLOT(player1PositionChanged(double)));
765 connect(m_pCOPlayPos2, SIGNAL(valueChanged(double)),
766- this, SLOT(player2PositionChanged(double)));
767-
768-
769- //Manually override the "next track is already loaded" flag
770- //because we've already primed a player with the first track.
771- //We do this so that you don't lose the first song in your
772- //Auto DJ queue if you enable Auto DJ then change your mind
773- //and disable it right away. This just makes it a little bit
774- //more user friendly. :)
775- //m_bNextTrackAlreadyLoaded = true;
776- m_bPlayer1Primed = false;
777- m_bPlayer2Primed = false;
778-
779- //If there are no tracks in the Auto DJ queue, disable Auto DJ mode.
780- /* if (m_pAutoDJTableModel->rowCount() == 0)
781- {
782- //Queue was empty. Disable and return.
783- pushButtonAutoDJ->setChecked(false);
784- return;
785- }*/ //don't need this code, above block takes care of this case.
786-
787- //If only one of the players is playing...
788- if ((m_pCOPlay1->get() == 1.0f && m_pCOPlay2->get() == 0.0f) ||
789- (m_pCOPlay1->get() == 0.0f && m_pCOPlay2->get() == 1.0f))
790- {
791- //Load the first song from the queue.
792- if (!loadNextTrackFromQueue(false)) {
793- //Queue was empty. Disable and return.
794- pushButtonAutoDJ->setChecked(false);
795- return;
796- }
797- //Set the primed flags so the crossfading algorithm knows
798- //that it doesn't need to load a track into whatever player.
799- if (m_pCOPlay1->get() == 1.0f)
800- {
801- m_bPlayer1Primed = true;
802- }
803- if (m_pCOPlay2->get() == 1.0f)
804- {
805- m_bPlayer2Primed = true;
806- }
807- }
808- //If both players are stopped, start the first one (which should have just had a track loaded into it)
809- else if (m_pCOPlay1->get() == 0.0f && m_pCOPlay2->get() == 0.0f) {
810- //Load the first song from the queue.
811- if (!loadNextTrackFromQueue(false)) {
812- //Queue was empty. Disable and return.
813- pushButtonAutoDJ->setChecked(false);
814- return;
815- }
816- m_pCOCrossfader->slotSet(-1.0f); //Move crossfader to the left!
817- m_pCORepeat1->slotSet(1.0f); //Turn on repeat mode to avoid race condition between async load
818- //and "play" command.
819- m_pCOPlay1->slotSet(1.0f); //Play the track in player 1
820- }
821- }
822- else //Disable Auto DJ
823- {
824+ this, SLOT(player2PositionChanged(double)));
825+
826+ connect(m_pCOPlay1Fb, SIGNAL(valueChanged(double)),
827+ this, SLOT(player1PlayChanged(double)));
828+ connect(m_pCOPlay2Fb, SIGNAL(valueChanged(double)),
829+ this, SLOT(player2PlayChanged(double)));
830+
831+ if (!deck1Playing && !deck2Playing) {
832+ // both decks are stopped
833+ m_eState = ADJ_ENABLE_P1LOADED;
834+ // Force Update on load Track
835+ m_pCOPlayPos1->slotSet(-0.001f);
836+ } else if (deck1Playing) {
837+ // deck 1 is already playing
838+ m_eState = ADJ_IDLE;
839+ player1PlayChanged(1.0f);
840+ } else {
841+ // deck 2 is already playing
842+ m_eState = ADJ_IDLE;
843+ player2PlayChanged(1.0f);
844+ }
845+ // Loads into first deck If stopped else into second else not
846+ emit(loadTrack(nextTrack));
847+ } else { // Disable Auto DJ
848+ pushButtonAutoDJ->setToolTip(tr("Enable Auto DJ"));
849 pushButtonAutoDJ->setText(tr("Enable Auto DJ"));
850 qDebug() << "Auto DJ disabled";
851 m_bAutoDJEnabled = false;
852+ m_bFadeNow = false;
853 m_pCOPlayPos1->disconnect(this);
854 m_pCOPlayPos2->disconnect(this);
855- m_pCORepeat1->slotSet(0.0f); //Turn off repeat mode
856- m_pCORepeat2->slotSet(0.0f); //Turn off repeat mode
857- }
858-}
859-
860-void DlgAutoDJ::player1PositionChanged(double value)
861-{
862- const float posThreshold = 0.95; //95% playback is when we crossfade and do stuff
863- if (value > posThreshold)
864- {
865- //Crossfade!
866- float crossfadeValue = -1.0f + 2*(value-posThreshold)/(1.0f-posThreshold);
867- m_pCOCrossfader->slotSet(crossfadeValue); //Move crossfader to the right!
868- //If the second player doesn't have a new track loaded in it...
869- if (!m_bPlayer2Primed)
870- {
871- qDebug() << "pp1c loading";
872-
873- //Load the next track into Player 2
874- //if (!m_bNextTrackAlreadyLoaded) //Fudge to make us not skip the first track
875- {
876- if (!loadNextTrackFromQueue(true))
877- return;
878- }
879- //m_bNextTrackAlreadyLoaded = false; //Reset fudge
880- m_bPlayer2Primed = true;
881- }
882- //If the second player is stopped...
883- if (m_pCOPlay2->get() == 0.0f)
884- {
885- //Turn off repeat mode to tell Player 1 to stop at the end
886- m_pCORepeat1->slotSet(0.0f);
887-
888- //Turn on repeat mode to tell Player 2 to start playing when the new track is loaded.
889- //This helps us get around the fact that it takes time for the track to be loaded
890- //and that is executed asynchronously (so we get around the race condition).
891- m_pCORepeat2->slotSet(1.0f);
892- //Play!
893- m_pCOPlay2->slotSet(1.0f);
894- }
895-
896- if (value == 1.0f)
897- {
898- m_pCOPlay1->slotSet(0.0f); //Stop the player
899- m_bPlayer1Primed = false;
900- }
901- }
902-}
903-
904-void DlgAutoDJ::player2PositionChanged(double value)
905-{
906- const float posThreshold = 0.95; //95% playback is when we crossfade and do stuff
907- if (value > posThreshold)
908- {
909- //Crossfade!
910- float crossfadeValue = 1.0f - 2*(value-posThreshold)/(1.0f-posThreshold);
911- m_pCOCrossfader->slotSet(crossfadeValue); //Move crossfader to the right!
912-
913- //If the first player doesn't have the next track loaded, load a track into
914- //it and start playing it!
915- if (!m_bPlayer1Primed)
916- {
917- //Load the next track into player 1
918- //if (!m_bNextTrackAlreadyLoaded) //Fudge to make us not skip the first track
919- {
920- if (!loadNextTrackFromQueue(true))
921- return;
922- }
923- //m_bNextTrackAlreadyLoaded = false; //Reset fudge
924- m_bPlayer1Primed = true;
925- }
926- if (m_pCOPlay1->get() == 0.0f)
927- {
928- //Turn off repeat mode to tell Player 2 to stop at the end
929- m_pCORepeat2->slotSet(0.0f);
930-
931- //Turn on repeat mode to tell Player 1 to start playing when the new track is loaded.
932- //This helps us get around the fact that it takes time for the track to be loaded
933- //and that is executed asynchronously (so we get around the race condition).
934- m_pCORepeat1->slotSet(1.0f);
935- m_pCOPlay1->slotSet(1.0f);
936- }
937-
938- if (value == 1.0f)
939- {
940- m_pCOPlay2->slotSet(0.0f); //Stop the player
941- m_bPlayer2Primed = false;
942- }
943- }
944-}
945-
946-
947-bool DlgAutoDJ::loadNextTrackFromQueue(bool removeTopMostBeforeLoading)
948-{
949- if (removeTopMostBeforeLoading) {
950- //Only remove the top track if this isn't the start of Auto DJ mode.
951- m_pAutoDJTableModel->removeTrack(m_pAutoDJTableModel->index(0, 0));
952- }
953-
954- //Get the track at the top of the playlist...
955- TrackPointer nextTrack = m_pAutoDJTableModel->getTrack(m_pAutoDJTableModel->index(0, 0));
956-
957- if (!nextTrack) //We ran out of tracks in the queue...
958- {
959- //Disable auto DJ and return...
960+ m_pCOPlay1->disconnect(this);
961+ m_pCOPlay2->disconnect(this);
962+ }
963+}
964+
965+void DlgAutoDJ::player1PositionChanged(double value) {
966+ // 95% playback is when we crossfade and do stuff
967+ // const float posThreshold = 0.95;
968+
969+ // 0.05; // 5% playback is crossfade duration
970+ const float fadeDuration = m_fadeDuration1;
971+
972+ // qDebug() << "player1PositionChanged(" << value << ")";
973+ if (!m_bAutoDJEnabled) {
974+ //nothing to do
975+ return;
976+ }
977+
978+ bool deck1Playing = m_pCOPlay1Fb->get() == 1.0f;
979+ bool deck2Playing = m_pCOPlay2Fb->get() == 1.0f;
980+
981+ if (m_eState == ADJ_ENABLE_P1LOADED) {
982+ // Auto DJ Start
983+ if (!deck1Playing && !deck2Playing) {
984+ m_pCOCrossfader->slotSet(-1.0f); // Move crossfader to the left!
985+ m_pCOPlay1->slotSet(1.0f); // Play the track in player 1
986+ removePlayingTrackFromQueue("[Channel1]");
987+ } else if (deck1Playing && !deck2Playing) {
988+ // Here we are, if first deck was playing before starting Auto DJ
989+ // or if it was started just before
990+ loadNextTrackFromQueue();
991+ m_eState = ADJ_IDLE;
992+ // if we start the deck from code we don`t get a signal
993+ player1PlayChanged(1.0f);
994+ // call function manually
995+ } else {
996+ m_eState = ADJ_IDLE;
997+ player2PlayChanged(1.0f);
998+ }
999+ return;
1000+ }
1001+
1002+ if (m_eState == ADJ_P2FADING) {
1003+ if (deck1Playing && !deck2Playing) {
1004+ loadNextTrackFromQueue();
1005+ // End State
1006+ m_pCOCrossfader->slotSet(-1.0f); // Move crossfader to the left!
1007+ // qDebug() << "1: m_pCOCrossfader->slotSet(_-1.0f_);";
1008+ m_eState = ADJ_IDLE;
1009+ }
1010+ return;
1011+ }
1012+
1013+ if (m_eState == ADJ_IDLE) {
1014+ if (m_pCORepeat1->get() == 1.0f) {
1015+ // repeat disables auto DJ
1016+ return;
1017+ }
1018+ }
1019+
1020+ if (value >= m_posThreshold1) {
1021+ if (m_eState == ADJ_IDLE &&
1022+ (deck1Playing || m_posThreshold1 >= 1.0f)) {
1023+ if (!deck2Playing) {
1024+ // Start Deck 2
1025+ player2PlayChanged(1.0f);
1026+ m_pCOPlay2->slotSet(1.0f);
1027+ if (fadeDuration < 0.0f) {
1028+ // Scroll back for pause between tracks
1029+ m_pCOPlayPos2->slotSet(m_fadeDuration2);
1030+ }
1031+ }
1032+ removePlayingTrackFromQueue("[Channel2]");
1033+ m_eState = ADJ_P1FADING;
1034+ }
1035+
1036+ float posFadeEnd = math_min(1.0, m_posThreshold1 + fadeDuration);
1037+
1038+ if (value >= posFadeEnd) {
1039+ // Pre-EndState
1040+ // m_pCOCrossfader->slotSet(1.0f); //Move crossfader to the right!
1041+
1042+ m_pCOPlay1->slotSet(0.0f); // Stop the player
1043+ //m_posThreshold = 1.0f - fadeDuration; // back to default
1044+
1045+ // does not work always immediately after stop
1046+ // loadNextTrackFromQueue();
1047+ // m_eState = ADJ_IDLE; // Fading ready
1048+ } else {
1049+ // Crossfade!
1050+ float crossfadeValue = -1.0f +
1051+ 2*(value-m_posThreshold1)/(posFadeEnd-m_posThreshold1);
1052+ // crossfadeValue = -1.0f -> + 1.0f
1053+ // Move crossfader to the right!
1054+ m_pCOCrossfader->slotSet(crossfadeValue);
1055+ // qDebug() << "1: m_pCOCrossfader->slotSet " << crossfadeValue;
1056+ }
1057+ }
1058+}
1059+
1060+void DlgAutoDJ::player2PositionChanged(double value) {
1061+ // 95% playback is when we crossfade and do stuff
1062+ // const float posThreshold = 0.95;
1063+
1064+ // 0.05; // 5% playback is crossfade duration
1065+ float fadeDuration = m_fadeDuration2;
1066+
1067+ //qDebug() << "player2PositionChanged(" << value << ")";
1068+ if (!m_bAutoDJEnabled) {
1069+ //nothing to do
1070+ return;
1071+ }
1072+
1073+ bool deck1Playing = m_pCOPlay1Fb->get() == 1.0f;
1074+ bool deck2Playing = m_pCOPlay2Fb->get() == 1.0f;
1075+
1076+ if (m_eState == ADJ_P1FADING) {
1077+ if (!deck1Playing && deck2Playing) {
1078+ // End State
1079+ // Move crossfader to the right!
1080+ m_pCOCrossfader->slotSet(1.0f);
1081+ // qDebug() << "1: m_pCOCrossfader->slotSet(_1.0f_);";
1082+ m_eState = ADJ_IDLE;
1083+ loadNextTrackFromQueue();
1084+ }
1085+ return;
1086+ }
1087+
1088+ if (m_eState == ADJ_IDLE) {
1089+ if (m_pCORepeat2->get() == 1.0f) {
1090+ //repeat disables auto DJ
1091+ return;
1092+ }
1093+ }
1094+
1095+ if (value >= m_posThreshold2) {
1096+ if (m_eState == ADJ_IDLE &&
1097+ (deck2Playing || m_posThreshold2 >= 1.0f)) {
1098+ if (!deck1Playing) {
1099+ player1PlayChanged(1.0f);
1100+ m_pCOPlay1->slotSet(1.0f);
1101+ if (fadeDuration < 0) {
1102+ // Scroll back for pause between tracks
1103+ m_pCOPlayPos1->slotSet(m_fadeDuration1);
1104+ }
1105+ }
1106+ removePlayingTrackFromQueue("[Channel1]");
1107+ m_eState = ADJ_P2FADING;
1108+ }
1109+
1110+ float posFadeEnd = math_min(1.0, m_posThreshold2 + fadeDuration);
1111+
1112+ if (value >= posFadeEnd) {
1113+ // Pre-End State
1114+ //m_pCOCrossfader->slotSet(-1.0f); //Move crossfader to the left!
1115+
1116+ m_pCOPlay2->slotSet(0.0f); // Stop the player
1117+
1118+ //m_posThreshold = 1.0f - fadeDuration; // back to default
1119+
1120+ // does not work always immediately after stop
1121+ // loadNextTrackFromQueue();
1122+ // m_eState = ADJ_IDLE; // Fading ready
1123+ } else {
1124+ //Crossfade!
1125+ float crossfadeValue = 1.0f -
1126+ 2*(value-m_posThreshold2)/(posFadeEnd-m_posThreshold2);
1127+ // crossfadeValue = 1.0f -> + -1.0f
1128+ m_pCOCrossfader->slotSet(crossfadeValue); //Move crossfader to the right!
1129+ // qDebug() << "2: m_pCOCrossfader->slotSet " << crossfadeValue;
1130+ }
1131+ }
1132+}
1133+
1134+TrackPointer DlgAutoDJ::getNextTrackFromQueue() {
1135+ // Get the track at the top of the playlist...
1136+ TrackPointer nextTrack;
1137+
1138+ while (true) {
1139+ nextTrack = m_pAutoDJTableModel->getTrack(
1140+ m_pAutoDJTableModel->index(0, 0));
1141+
1142+ if (nextTrack) {
1143+ if (nextTrack->exists()) {
1144+ // found a valid Track
1145+ return nextTrack;
1146+ } else {
1147+ // Remove missing song from auto DJ playlist
1148+ m_pAutoDJTableModel->removeTrack(
1149+ m_pAutoDJTableModel->index(0, 0));
1150+ }
1151+ } else {
1152+ // we are running out of tracks
1153+ break;
1154+ }
1155+ }
1156+ return nextTrack;
1157+}
1158+
1159+bool DlgAutoDJ::loadNextTrackFromQueue() {
1160+ TrackPointer nextTrack = getNextTrackFromQueue();
1161+
1162+ // We ran out of tracks in the queue...
1163+ if (!nextTrack) {
1164+ // Disable auto DJ and return...
1165 pushButtonAutoDJ->setChecked(false);
1166 return false;
1167 }
1168
1169- //m_bNextTrackAlreadyLoaded = false;
1170-
1171 emit(loadTrack(nextTrack));
1172-
1173- return true;
1174+ return true;
1175+}
1176+
1177+bool DlgAutoDJ::removePlayingTrackFromQueue(QString group) {
1178+ TrackPointer nextTrack, loadedTrack;
1179+ int nextId = 0, loadedId = 0;
1180+
1181+ // Get the track at the top of the playlist...
1182+ nextTrack = m_pAutoDJTableModel->getTrack(m_pAutoDJTableModel->index(0, 0));
1183+ if (nextTrack) {
1184+ nextId = nextTrack->getId();
1185+ }
1186+
1187+ // Get loaded track
1188+ loadedTrack = PlayerInfo::Instance().getTrackInfo(group);
1189+ if (loadedTrack) {
1190+ loadedId = loadedTrack->getId();
1191+ }
1192+
1193+ // When enable auto DJ and Topmost Song is already on second deck, nothing to do
1194+ // BaseTrackPlayer::getLoadedTrack()
1195+ // pTrack = PlayerInfo::Instance().getCurrentPlayingTrack();
1196+
1197+ if (loadedId != nextId) {
1198+ // Do not remove when the user has loaded a track manualy
1199+ return false;
1200+ }
1201+
1202+ // remove the top track
1203+ m_pAutoDJTableModel->removeTrack(m_pAutoDJTableModel->index(0, 0));
1204+
1205+ return true;
1206+}
1207+
1208+void DlgAutoDJ::player1PlayChanged(double value) {
1209+ //qDebug() << "player1PlayChanged(" << value << ")";
1210+ if (!m_bAutoDJEnabled) {
1211+ return;
1212+ }
1213+
1214+ if (value == 1.0f && m_eState == ADJ_IDLE) {
1215+ TrackPointer loadedTrack =
1216+ PlayerInfo::Instance().getTrackInfo("[Channel1]");
1217+ if (loadedTrack) {
1218+ int TrackDuration = loadedTrack->getDuration();
1219+ qDebug() << "TrackDuration = " << TrackDuration;
1220+
1221+ int autoDjTransition = spinBoxTransition->value();
1222+
1223+ if (TrackDuration > autoDjTransition) {
1224+ m_fadeDuration1 = static_cast<float>(autoDjTransition) /
1225+ static_cast<float>(TrackDuration);
1226+ } else {
1227+ m_fadeDuration1 = 0;
1228+ }
1229+
1230+ if (autoDjTransition > 0) {
1231+ m_posThreshold1 = 1.0f - m_fadeDuration1;
1232+ } else {
1233+ // in case of pause
1234+ m_posThreshold1 = 1.0f;
1235+ }
1236+ qDebug() << "m_fadeDuration1 = " << m_fadeDuration1;
1237+ }
1238+ }
1239+}
1240+
1241+void DlgAutoDJ::player2PlayChanged(double value) {
1242+ //qDebug() << "player2PlayChanged(" << value << ")";
1243+ if (!m_bAutoDJEnabled) {
1244+ return;
1245+ }
1246+
1247+ if (value == 1.0f && m_eState == ADJ_IDLE) {
1248+ TrackPointer loadedTrack =
1249+ PlayerInfo::Instance().getTrackInfo("[Channel2]");
1250+ if (loadedTrack) {
1251+ int TrackDuration = loadedTrack->getDuration();
1252+ qDebug() << "TrackDuration = " << TrackDuration;
1253+
1254+ int autoDjTransition = spinBoxTransition->value();
1255+
1256+ if (TrackDuration > autoDjTransition) {
1257+ m_fadeDuration2 = static_cast<float>(autoDjTransition) /
1258+ static_cast<float>(TrackDuration);
1259+ } else {
1260+ m_fadeDuration2 = 0;
1261+ }
1262+
1263+ if (autoDjTransition > 0) {
1264+ m_posThreshold2 = 1.0f - m_fadeDuration2;
1265+ } else {
1266+ // in case of pause
1267+ m_posThreshold2 = 1.0f;
1268+ }
1269+ qDebug() << "m_fadeDuration2 = " << m_fadeDuration2;
1270+ }
1271+ }
1272+}
1273+
1274+void DlgAutoDJ::transitionValueChanged(int value) {
1275+ if (m_bAutoDJEnabled && m_eState == ADJ_IDLE) {
1276+ if (m_pCOPlay1Fb->get() == 1.0f) {
1277+ player1PlayChanged(1.0f);
1278+ }
1279+ if (m_pCOPlay2Fb->get() == 1.0f) {
1280+ player2PlayChanged(1.0f);
1281+ }
1282+ }
1283+ m_pConfig->set(ConfigKey(CONFIG_KEY, kTransitionPreferenceName),
1284+ ConfigValue(value));
1285+}
1286+
1287+bool DlgAutoDJ::appendTrack(int trackId) {
1288+ return m_pAutoDJTableModel->appendTrack(trackId);
1289 }
1290
1291=== modified file 'mixxx/src/dlgautodj.h'
1292--- mixxx/src/dlgautodj.h 2011-04-24 06:00:11 +0000
1293+++ mixxx/src/dlgautodj.h 2012-03-12 04:06:20 +0000
1294@@ -31,19 +31,35 @@
1295 virtual void loadSelectedTrack();
1296 virtual void loadSelectedTrackToGroup(QString group);
1297 virtual void moveSelection(int delta);
1298+ virtual bool appendTrack(int trackId);
1299
1300 public slots:
1301 void shufflePlaylist(bool buttonChecked);
1302+ void skipNext(bool buttonChecked);
1303+ void fadeNow(bool buttonChecked);
1304 void toggleAutoDJ(bool toggle);
1305 void player1PositionChanged(double value);
1306 void player2PositionChanged(double value);
1307+ void player1PlayChanged(double value);
1308+ void player2PlayChanged(double value);
1309+ void transitionValueChanged(int value);
1310
1311 signals:
1312 void loadTrack(TrackPointer tio);
1313 void loadTrackToPlayer(TrackPointer tio, QString group);
1314
1315 private:
1316- bool loadNextTrackFromQueue(bool removeTopMostBeforeLoading);
1317+ enum ADJstates {
1318+ ADJ_IDLE = 0,
1319+ ADJ_P1FADING,
1320+ ADJ_P2FADING,
1321+ ADJ_ENABLE_P1LOADED,
1322+ ADJ_ENABLE_P1PLAYING
1323+ };
1324+
1325+ TrackPointer getNextTrackFromQueue();
1326+ bool loadNextTrackFromQueue();
1327+ bool removePlayingTrackFromQueue(QString group);
1328
1329 ConfigObject<ConfigValue>* m_pConfig;
1330 TrackCollection* m_pTrackCollection;
1331@@ -51,17 +67,24 @@
1332 PlaylistTableModel* m_pAutoDJTableModel;
1333 PlaylistDAO& m_playlistDao;
1334 bool m_bAutoDJEnabled;
1335- bool m_bNextTrackAlreadyLoaded; /** Makes our Auto DJ logic assume the
1336- next track that should be played is
1337- already loaded. We need this flag to
1338- make our first-track-gets-loaded-but-
1339- not-removed-from-the-queue behaviour
1340- work. */
1341- bool m_bPlayer1Primed, m_bPlayer2Primed;
1342+
1343+ // Makes our Auto DJ logic assume the next track that should be played is
1344+ // already loaded. We need this flag to make our
1345+ // first-track-gets-loaded-but- not-removed-from-the-queue behaviour work.
1346+ bool m_bNextTrackAlreadyLoaded;
1347+
1348+ bool m_bFadeNow;
1349+ enum ADJstates m_eState;
1350+ float m_posThreshold1;
1351+ float m_posThreshold2;
1352+ float m_fadeDuration1;
1353+ float m_fadeDuration2;
1354 ControlObjectThreadMain* m_pCOPlayPos1;
1355 ControlObjectThreadMain* m_pCOPlayPos2;
1356 ControlObjectThreadMain* m_pCOPlay1;
1357 ControlObjectThreadMain* m_pCOPlay2;
1358+ ControlObjectThreadMain* m_pCOPlay1Fb;
1359+ ControlObjectThreadMain* m_pCOPlay2Fb;
1360 ControlObjectThreadMain* m_pCORepeat1;
1361 ControlObjectThreadMain* m_pCORepeat2;
1362 ControlObjectThreadMain* m_pCOCrossfader;
1363@@ -82,7 +105,7 @@
1364
1365
1366 #define _blah if ((QDate::currentDate().day() == 1) && (QDate::currentDate().month() == 4)) \
1367- pushButtonAutoDJ->setText("\x45\x6e\x61\x62\x6c\x65\x20\x50\x65\x65" \
1368+ pushButtonAutoDJ->setText("\x45\x6e\x61\x62\x6c\x65\x20\x50\x65\x65" \
1369 "\x20\x42\x72\x65\x61\x6b\x20\x4d\x6f\x64\x65")
1370
1371
1372
1373=== modified file 'mixxx/src/dlgautodj.ui'
1374--- mixxx/src/dlgautodj.ui 2011-10-05 03:30:02 +0000
1375+++ mixxx/src/dlgautodj.ui 2012-03-12 04:06:20 +0000
1376@@ -6,13 +6,28 @@
1377 <rect>
1378 <x>0</x>
1379 <y>0</y>
1380- <width>582</width>
1381+ <width>500</width>
1382 <height>399</height>
1383 </rect>
1384 </property>
1385 <property name="windowTitle">
1386 <string>Manage</string>
1387 </property>
1388+ <property name="styleSheet">
1389+ <string notr="true">#pushButtonShuffle{
1390+ border-image: url(:/images/autodj/media-playlist-shuffle.svg);
1391+}
1392+
1393+#pushButtonSkipNext{
1394+ border-image: url(:/images/autodj/bottom.svg);
1395+}
1396+
1397+#pushButtonFadeNow{
1398+ border-image: url(:/images/autodj/stock_mail-send-receive.svg);
1399+}
1400+
1401+</string>
1402+ </property>
1403 <layout class="QVBoxLayout" name="verticalLayout">
1404 <property name="leftMargin">
1405 <number>0</number>
1406@@ -25,13 +40,89 @@
1407 </property>
1408 <item>
1409 <layout class="QHBoxLayout" name="horizontalLayout">
1410+ <property name="sizeConstraint">
1411+ <enum>QLayout::SetMinimumSize</enum>
1412+ </property>
1413 <item>
1414 <widget class="QPushButton" name="pushButtonShuffle">
1415- <property name="text">
1416- <string>Shuffle playlist</string>
1417- </property>
1418- <property name="checkable">
1419- <bool>false</bool>
1420+ <property name="maximumSize">
1421+ <size>
1422+ <width>24</width>
1423+ <height>24</height>
1424+ </size>
1425+ </property>
1426+ <property name="toolTip">
1427+ <string>Shuffle Playlist</string>
1428+ </property>
1429+ <property name="text">
1430+ <string/>
1431+ </property>
1432+ <property name="checkable">
1433+ <bool>false</bool>
1434+ </property>
1435+ </widget>
1436+ </item>
1437+ <item>
1438+ <widget class="QPushButton" name="pushButtonSkipNext">
1439+ <property name="maximumSize">
1440+ <size>
1441+ <width>24</width>
1442+ <height>24</height>
1443+ </size>
1444+ </property>
1445+ <property name="toolTip">
1446+ <string>Skip Next Track</string>
1447+ </property>
1448+ <property name="text">
1449+ <string/>
1450+ </property>
1451+ <property name="checkable">
1452+ <bool>false</bool>
1453+ </property>
1454+ </widget>
1455+ </item>
1456+ <item>
1457+ <widget class="QLabel" name="label_2">
1458+ <property name="text">
1459+ <string>Transition [sec]</string>
1460+ </property>
1461+ </widget>
1462+ </item>
1463+ <item>
1464+ <widget class="QSpinBox" name="spinBoxTransition">
1465+ <property name="sizePolicy">
1466+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
1467+ <horstretch>0</horstretch>
1468+ <verstretch>0</verstretch>
1469+ </sizepolicy>
1470+ </property>
1471+ <property name="maximumSize">
1472+ <size>
1473+ <width>45</width>
1474+ <height>16777215</height>
1475+ </size>
1476+ </property>
1477+ <property name="alignment">
1478+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
1479+ </property>
1480+ <property name="minimum">
1481+ <number>-9</number>
1482+ </property>
1483+ </widget>
1484+ </item>
1485+ <item>
1486+ <widget class="QPushButton" name="pushButtonFadeNow">
1487+ <property name="maximumSize">
1488+ <size>
1489+ <width>24</width>
1490+ <height>24</height>
1491+ </size>
1492+ </property>
1493+ <property name="toolTip">
1494+ <string>Fade Now</string>
1495+ </property>
1496+ <property name="text">
1497+ <string/>
1498 </property>
1499 </widget>
1500 </item>
1501@@ -42,24 +133,17 @@
1502 </property>
1503 <property name="sizeHint" stdset="0">
1504 <size>
1505- <width>40</width>
1506+ <width>1</width>
1507 <height>20</height>
1508 </size>
1509 </property>
1510 </spacer>
1511 </item>
1512 <item>
1513- <widget class="QLabel" name="label">
1514- <property name="text">
1515- <string>Add tracks to the queue below...</string>
1516- </property>
1517- <property name="buddy" >
1518- <cstring>m_pTrackTablePlaceholder</cstring>
1519- </property>
1520- </widget>
1521- </item>
1522- <item>
1523 <widget class="QPushButton" name="pushButtonAutoDJ">
1524+ <property name="toolTip">
1525+ <string>Enable Auto DJ</string>
1526+ </property>
1527 <property name="text">
1528 <string>Enable Auto DJ</string>
1529 </property>
1530@@ -88,6 +172,12 @@
1531 </item>
1532 <item>
1533 <widget class="QTableView" name="m_pTrackTablePlaceholder">
1534+ <property name="sizePolicy">
1535+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1536+ <horstretch>0</horstretch>
1537+ <verstretch>0</verstretch>
1538+ </sizepolicy>
1539+ </property>
1540 <property name="showGrid">
1541 <bool>true</bool>
1542 </property>
1543@@ -95,6 +185,8 @@
1544 </item>
1545 </layout>
1546 </widget>
1547- <resources/>
1548+ <resources>
1549+ <include location="../res/mixxx.qrc"/>
1550+ </resources>
1551 <connections/>
1552 </ui>
1553
1554=== modified file 'mixxx/src/library/autodjfeature.cpp'
1555--- mixxx/src/library/autodjfeature.cpp 2011-10-12 17:29:43 +0000
1556+++ mixxx/src/library/autodjfeature.cpp 2012-03-12 04:06:20 +0000
1557@@ -23,6 +23,7 @@
1558 m_pConfig(pConfig),
1559 m_pTrackCollection(pTrackCollection),
1560 m_playlistDao(pTrackCollection->getPlaylistDAO()) {
1561+ m_pAutoDJView = NULL;
1562 }
1563
1564 AutoDJFeature::~AutoDJFeature() {
1565@@ -36,47 +37,43 @@
1566 return QIcon(":/images/library/ic_library_autodj.png");
1567 }
1568
1569-void AutoDJFeature::bindWidget(WLibrarySidebar* sidebarWidget,
1570+void AutoDJFeature::bindWidget(WLibrarySidebar* /*sidebarWidget*/,
1571 WLibrary* libraryWidget,
1572 MixxxKeyboard* keyboard) {
1573-
1574- DlgAutoDJ* pAutoDJView = new DlgAutoDJ(libraryWidget,
1575- m_pConfig,
1576- m_pTrackCollection,
1577- keyboard);
1578- pAutoDJView->installEventFilter(keyboard);
1579- libraryWidget->registerView(m_sAutoDJViewName, pAutoDJView);
1580- connect(pAutoDJView, SIGNAL(loadTrack(TrackPointer)),
1581+ m_pAutoDJView = new DlgAutoDJ(libraryWidget,
1582+ m_pConfig,
1583+ m_pTrackCollection,
1584+ keyboard);
1585+ m_pAutoDJView->installEventFilter(keyboard);
1586+ libraryWidget->registerView(m_sAutoDJViewName, m_pAutoDJView);
1587+ connect(m_pAutoDJView, SIGNAL(loadTrack(TrackPointer)),
1588 this, SIGNAL(loadTrack(TrackPointer)));
1589- connect(pAutoDJView, SIGNAL(loadTrackToPlayer(TrackPointer, QString)),
1590+ connect(m_pAutoDJView, SIGNAL(loadTrackToPlayer(TrackPointer, QString)),
1591 this, SIGNAL(loadTrackToPlayer(TrackPointer, QString)));
1592 }
1593
1594 TreeItemModel* AutoDJFeature::getChildModel() {
1595- return &m_childModel;
1596+ return &m_childModel;
1597 }
1598
1599 void AutoDJFeature::activate() {
1600 //qDebug() << "AutoDJFeature::activate()";
1601 //emit(showTrackModel(m_pAutoDJTableModelProxy));
1602- emit(switchToView("Auto DJ"));
1603-}
1604-
1605-void AutoDJFeature::activateChild(const QModelIndex& index) {
1606-
1607-}
1608-
1609-void AutoDJFeature::onRightClick(const QPoint& globalPos) {
1610-}
1611-
1612-void AutoDJFeature::onRightClickChild(const QPoint& globalPos,
1613- QModelIndex index) {
1614+ emit(switchToView(m_sAutoDJViewName));
1615+}
1616+
1617+void AutoDJFeature::activateChild(const QModelIndex& /*index*/) {
1618+}
1619+
1620+void AutoDJFeature::onRightClick(const QPoint& /*globalPos*/) {
1621+}
1622+
1623+void AutoDJFeature::onRightClickChild(const QPoint& /*globalPos*/,
1624+ QModelIndex /*index*/) {
1625 }
1626
1627 bool AutoDJFeature::dropAccept(QUrl url) {
1628-
1629 //TODO: Filter by supported formats regex and reject anything that doesn't match.
1630-
1631 TrackDAO &trackDao = m_pTrackCollection->getTrackDAO();
1632
1633 //If a track is dropped onto a playlist's name, but the track isn't in the library,
1634@@ -98,12 +95,17 @@
1635 }
1636
1637 // TODO(XXX) No feedback on whether this worked.
1638- int playlistId = m_playlistDao.getPlaylistIdFromName(AUTODJ_TABLE);
1639- m_playlistDao.appendTrackToPlaylist(trackId, playlistId);
1640+ if (m_pAutoDJView) {
1641+ m_pAutoDJView->appendTrack(trackId);
1642+ } else {
1643+ int playlistId = m_playlistDao.getPlaylistIdFromName(AUTODJ_TABLE);
1644+ m_playlistDao.appendTrackToPlaylist(trackId, playlistId);
1645+ }
1646+
1647 return true;
1648 }
1649
1650-bool AutoDJFeature::dropAcceptChild(const QModelIndex& index, QUrl url) {
1651+bool AutoDJFeature::dropAcceptChild(const QModelIndex& /*index*/, QUrl /*url*/) {
1652 return false;
1653 }
1654
1655@@ -112,10 +114,10 @@
1656 return SoundSourceProxy::isFilenameSupported(file.fileName());
1657 }
1658
1659-bool AutoDJFeature::dragMoveAcceptChild(const QModelIndex& index,
1660- QUrl url) {
1661+bool AutoDJFeature::dragMoveAcceptChild(const QModelIndex& /*index*/,
1662+ QUrl /*url*/) {
1663 return false;
1664 }
1665-void AutoDJFeature::onLazyChildExpandation(const QModelIndex &index){
1666+void AutoDJFeature::onLazyChildExpandation(const QModelIndex& /*index*/){
1667 //Nothing to do because the childmodel is not of lazy nature.
1668 }
1669
1670=== modified file 'mixxx/src/library/autodjfeature.h'
1671--- mixxx/src/library/autodjfeature.h 2011-03-10 13:37:21 +0000
1672+++ mixxx/src/library/autodjfeature.h 2012-03-12 04:06:20 +0000
1673@@ -11,13 +11,14 @@
1674 #include "library/dao/playlistdao.h"
1675 #include "configobject.h"
1676 #include "treeitemmodel.h"
1677+#include "dlgautodj.h"
1678
1679 class PlaylistTableModel;
1680 class TrackCollection;
1681
1682 class AutoDJFeature : public LibraryFeature {
1683 Q_OBJECT
1684- public:
1685+ public:
1686 AutoDJFeature(QObject* parent,
1687 ConfigObject<ConfigValue>* pConfig,
1688 TrackCollection* pTrackCollection);
1689@@ -37,19 +38,20 @@
1690
1691 TreeItemModel* getChildModel();
1692
1693-public slots:
1694+ public slots:
1695 void activate();
1696 void activateChild(const QModelIndex& index);
1697 void onRightClick(const QPoint& globalPos);
1698 void onRightClickChild(const QPoint& globalPos, QModelIndex index);
1699 void onLazyChildExpandation(const QModelIndex& index);
1700
1701-private:
1702+ private:
1703 ConfigObject<ConfigValue>* m_pConfig;
1704 TrackCollection* m_pTrackCollection;
1705 PlaylistDAO& m_playlistDao;
1706 const static QString m_sAutoDJViewName;
1707 TreeItemModel m_childModel;
1708+ DlgAutoDJ* m_pAutoDJView;
1709 };
1710
1711
1712
1713=== modified file 'mixxx/src/library/browse/browsefeature.cpp'
1714--- mixxx/src/library/browse/browsefeature.cpp 2012-01-07 08:36:51 +0000
1715+++ mixxx/src/library/browse/browsefeature.cpp 2012-03-12 04:06:20 +0000
1716@@ -14,7 +14,8 @@
1717 #include "library/trackcollection.h"
1718 #include "library/dao/trackdao.h"
1719
1720-BrowseFeature::BrowseFeature(QObject* parent, ConfigObject<ConfigValue>* pConfig,
1721+BrowseFeature::BrowseFeature(QObject* parent,
1722+ ConfigObject<ConfigValue>* pConfig,
1723 TrackCollection* pTrackCollection,
1724 RecordingManager* pRecordingManager)
1725 : LibraryFeature(parent),
1726@@ -22,44 +23,47 @@
1727 m_browseModel(this, pTrackCollection, pRecordingManager),
1728 m_proxyModel(&m_browseModel),
1729 m_pTrackCollection(pTrackCollection) {
1730-
1731 m_proxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);
1732 m_proxyModel.setSortCaseSensitivity(Qt::CaseInsensitive);
1733
1734- //The invisible root item of the child model
1735+ // The invisible root item of the child model
1736 TreeItem* rootItem = new TreeItem();
1737
1738- TreeItem* quick_link = new TreeItem(tr("Quick Links"), QUICK_LINK_NODE ,this , rootItem);
1739+ TreeItem* quick_link = new TreeItem(
1740+ tr("Quick Links"), QUICK_LINK_NODE, this, rootItem);
1741 rootItem->appendChild(quick_link);
1742
1743- //Create the 'devices' shortcut
1744+ // Create the 'devices' shortcut
1745 #if defined(__WINDOWS__)
1746- TreeItem* devices_link = new TreeItem(tr("Devices"), DEVICE_NODE ,this , rootItem);
1747+ TreeItem* devices_link = new TreeItem(
1748+ tr("Devices"), DEVICE_NODE, this, rootItem);
1749 rootItem->appendChild(devices_link);
1750- //show drive letters
1751+ // show drive letters
1752 QFileInfoList drives = QDir::drives();
1753- //show drive letters
1754- foreach(QFileInfo drive, drives){
1755+ // show drive letters
1756+ foreach (QFileInfo drive, drives) {
1757 TreeItem* driveLetter = new TreeItem(
1758- drive.canonicalPath(), // displays C:
1759- drive.filePath(), //Displays C:/
1760- this ,
1761- devices_link);
1762+ drive.canonicalPath(), // displays C:
1763+ drive.filePath(), // Displays C:/
1764+ this ,
1765+ devices_link);
1766 devices_link->appendChild(driveLetter);
1767 }
1768 #elif defined(__APPLE__)
1769- //Apple hides the base Linux file structure
1770- //But all devices are mounted at /Volumes
1771- TreeItem* devices_link = new TreeItem(tr("Devices"), "/Volumes/", this , rootItem);
1772+ // Apple hides the base Linux file structure But all devices are mounted at
1773+ // /Volumes
1774+ TreeItem* devices_link = new TreeItem(
1775+ tr("Devices"), "/Volumes/", this, rootItem);
1776 rootItem->appendChild(devices_link);
1777-#else //LINUX
1778- TreeItem* devices_link = new TreeItem(tr("Removable Devices"), "/media/", this , rootItem);
1779+#else // LINUX
1780+ TreeItem* devices_link = new TreeItem(
1781+ tr("Removable Devices"), "/media/", this, rootItem);
1782 rootItem->appendChild(devices_link);
1783
1784- //show root directory on UNIX-based operating systems
1785- TreeItem* root_folder_item = new TreeItem(QDir::rootPath(), QDir::rootPath(),this , rootItem);
1786+ // show root directory on UNIX-based operating systems
1787+ TreeItem* root_folder_item = new TreeItem(
1788+ QDir::rootPath(), QDir::rootPath(), this, rootItem);
1789 rootItem->appendChild(root_folder_item);
1790-
1791 #endif
1792
1793 /*
1794@@ -76,34 +80,43 @@
1795 * deletion.
1796 */
1797
1798- //Add a shortcut to the Music folder which Mixxx uses
1799- QString mixxx_music_dir = m_pConfig->getValueString(ConfigKey("[Playlist]","Directory"));
1800- QString os_music_folder_dir = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);
1801- QString os_documents_folder_dir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
1802- QString os_home_folder_dir = QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
1803- QString os_desktop_folder_dir = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
1804+ // Add a shortcut to the Music folder which Mixxx uses
1805+ QString mixxx_music_dir = m_pConfig->getValueString(
1806+ ConfigKey("[Playlist]", "Directory"));
1807+ QString os_music_folder_dir = QDesktopServices::storageLocation(
1808+ QDesktopServices::MusicLocation);
1809+ QString os_documents_folder_dir = QDesktopServices::storageLocation(
1810+ QDesktopServices::DocumentsLocation);
1811+ QString os_home_folder_dir = QDesktopServices::storageLocation(
1812+ QDesktopServices::HomeLocation);
1813+ QString os_desktop_folder_dir = QDesktopServices::storageLocation(
1814+ QDesktopServices::DesktopLocation);
1815
1816- TreeItem* mixxx_library_dir_item = new TreeItem(tr("Mixxx Library"), mixxx_music_dir +"/" ,this , quick_link);
1817+ TreeItem* mixxx_library_dir_item = new TreeItem(
1818+ tr("Mixxx Library"), mixxx_music_dir + "/", this, quick_link);
1819 quick_link->appendChild(mixxx_library_dir_item);
1820
1821- TreeItem*os_home_dir_item = new TreeItem(tr("Home"), os_home_folder_dir +"/" , this , quick_link);
1822+ TreeItem* os_home_dir_item = new TreeItem(
1823+ tr("Home"), os_home_folder_dir + "/", this, quick_link);
1824 quick_link->appendChild(os_home_dir_item);
1825
1826- TreeItem*os_music_dir_item = new TreeItem(tr("Music"), os_music_folder_dir +"/" , this , quick_link);
1827+ TreeItem* os_music_dir_item = new TreeItem(
1828+ tr("Music"), os_music_folder_dir + "/", this, quick_link);
1829 quick_link->appendChild(os_music_dir_item);
1830
1831- TreeItem*os_docs_dir_item = new TreeItem(tr("Documents"), os_documents_folder_dir +"/" , this , quick_link);
1832+ TreeItem* os_docs_dir_item = new TreeItem(
1833+ tr("Documents"), os_documents_folder_dir + "/", this, quick_link);
1834 quick_link->appendChild(os_docs_dir_item);
1835
1836- TreeItem*os_desktop_dir_item = new TreeItem(tr("Desktop"), os_desktop_folder_dir +"/" , this , quick_link);
1837+ TreeItem* os_desktop_dir_item = new TreeItem(
1838+ tr("Desktop"), os_desktop_folder_dir + "/", this, quick_link);
1839 quick_link->appendChild(os_desktop_dir_item);
1840
1841- //initialize the model
1842+ // initialize the model
1843 m_childModel.setRootItem(rootItem);
1844 }
1845
1846 BrowseFeature::~BrowseFeature() {
1847-
1848 }
1849
1850 QVariant BrowseFeature::title() {
1851@@ -119,18 +132,24 @@
1852 }
1853
1854 bool BrowseFeature::dropAccept(QUrl url) {
1855+ Q_UNUSED(url);
1856 return false;
1857 }
1858
1859 bool BrowseFeature::dropAcceptChild(const QModelIndex& index, QUrl url) {
1860+ Q_UNUSED(index);
1861+ Q_UNUSED(url);
1862 return false;
1863 }
1864
1865 bool BrowseFeature::dragMoveAccept(QUrl url) {
1866+ Q_UNUSED(url);
1867 return false;
1868 }
1869
1870 bool BrowseFeature::dragMoveAcceptChild(const QModelIndex& index, QUrl url) {
1871+ Q_UNUSED(index);
1872+ Q_UNUSED(url);
1873 return false;
1874 }
1875
1876@@ -143,59 +162,64 @@
1877 */
1878 void BrowseFeature::activateChild(const QModelIndex& index) {
1879 TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
1880- qDebug() << "BrowseFeature::activateChild " << item->data() << " " << item->dataPath();
1881+ qDebug() << "BrowseFeature::activateChild " << item->data() << " "
1882+ << item->dataPath();
1883 m_browseModel.setPath(item->dataPath().toString());
1884 emit(showTrackModel(&m_proxyModel));
1885-
1886 }
1887
1888 void BrowseFeature::onRightClick(const QPoint& globalPos) {
1889-}
1890-
1891-void BrowseFeature::onRightClickChild(const QPoint& globalPos, QModelIndex index) {
1892-}
1893+ Q_UNUSED(globalPos);
1894+}
1895+
1896+void BrowseFeature::onRightClickChild(const QPoint& globalPos,
1897+ QModelIndex index) {
1898+ Q_UNUSED(globalPos);
1899+ Q_UNUSED(index);
1900+}
1901+
1902 /*
1903 * This is called whenever you double click or use the triangle symbol to expand
1904 * the subtree. The method will read the subfolders.
1905 */
1906 void BrowseFeature::onLazyChildExpandation(const QModelIndex &index){
1907 TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
1908- qDebug() << "BrowseFeature::onLazyChildExpandation " << item->data() << " " << item->dataPath();
1909+ qDebug() << "BrowseFeature::onLazyChildExpandation " << item->data()
1910+ << " " << item->dataPath();
1911
1912 // If the item is a build-in node, e.g., 'QuickLink' return
1913- if(item->dataPath().toString() == QUICK_LINK_NODE)
1914+ if (item->dataPath().toString() == QUICK_LINK_NODE) {
1915 return;
1916+ }
1917
1918- //Before we populate the subtree, we need to delete old subtrees
1919- m_childModel.removeRows(0, item->childCount(), index);
1920+ // Before we populate the subtree, we need to delete old subtrees
1921+ m_childModel.removeRows(0, item->childCount(), index);
1922
1923 // List of subfolders or drive letters
1924 QList<TreeItem*> folders;
1925
1926 // If we are on the special device node
1927- if(item->dataPath().toString() == DEVICE_NODE){
1928- //Repopulate drive list
1929+ if (item->dataPath().toString() == DEVICE_NODE) {
1930+ // Repopulate drive list
1931 QFileInfoList drives = QDir::drives();
1932- //show drive letters
1933- foreach(QFileInfo drive, drives){
1934+ // show drive letters
1935+ foreach (QFileInfo drive, drives) {
1936 TreeItem* driveLetter = new TreeItem(
1937- drive.canonicalPath(), // displays C:
1938- drive.filePath(), //Displays C:/
1939- this ,
1940- item);
1941+ drive.canonicalPath(), // displays C:
1942+ drive.filePath(), //Displays C:/
1943+ this ,
1944+ item);
1945 folders << driveLetter;
1946 }
1947-
1948- }
1949- else // we assume that the path refers to a folder in the file system
1950- {
1951- //populate childs
1952+ } else { // we assume that the path refers to a folder in the file system
1953+ // populate childs
1954 QDir dir(item->dataPath().toString());
1955- QFileInfoList all = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
1956+ QFileInfoList all = dir.entryInfoList(
1957+ QDir::Dirs | QDir::NoDotAndDotDot);
1958
1959 // loop through all the item and construct the childs
1960- foreach(QFileInfo one, all){
1961- //Skip folders that end with .app on OS X
1962+ foreach (QFileInfo one, all) {
1963+ // Skip folders that end with .app on OS X
1964 #if defined(__APPLE__)
1965 if (one.isDir() && one.fileName().endsWith(".app"))
1966 continue;
1967@@ -203,15 +227,17 @@
1968 // We here create new items for the sidebar models
1969 // Once the items are added to the TreeItemModel,
1970 // the models takes ownership of them and ensures their deletion
1971- TreeItem* folder = new TreeItem(one.fileName(),
1972- item->dataPath().toString().append(one.fileName() +"/"),
1973- this,
1974- item);
1975+ TreeItem* folder = new TreeItem(
1976+ one.fileName(),
1977+ item->dataPath().toString().append(one.fileName() +"/"),
1978+ this, item);
1979 folders << folder;
1980 }
1981 }
1982- //we need to check here if subfolders are found
1983- //On Ubuntu 10.04, otherwise, this will draw an icon although the folder has no subfolders
1984- if(!folders.isEmpty())
1985- m_childModel.insertRows(folders, 0, folders.size() , index);
1986+ // we need to check here if subfolders are found
1987+ // On Ubuntu 10.04, otherwise, this will draw an icon although the folder
1988+ // has no subfolders
1989+ if (!folders.isEmpty()) {
1990+ m_childModel.insertRows(folders, 0, folders.size() , index);
1991+ }
1992 }
1993
1994=== modified file 'mixxx/src/library/browse/browsefeature.h'
1995--- mixxx/src/library/browse/browsefeature.h 2011-03-30 21:53:33 +0000
1996+++ mixxx/src/library/browse/browsefeature.h 2012-03-12 04:06:20 +0000
1997@@ -44,8 +44,8 @@
1998 void onRightClickChild(const QPoint& globalPos, QModelIndex index);
1999
2000 void onLazyChildExpandation(const QModelIndex& index);
2001-
2002- signals:
2003+
2004+ signals:
2005 void setRootIndex(const QModelIndex&);
2006
2007 private:
2008
2009=== modified file 'mixxx/src/library/browse/browsetablemodel.cpp'
2010--- mixxx/src/library/browse/browsetablemodel.cpp 2011-12-28 20:30:15 +0000
2011+++ mixxx/src/library/browse/browsetablemodel.cpp 2012-03-12 04:06:20 +0000
2012@@ -16,13 +16,14 @@
2013 #include "audiotagger.h"
2014
2015
2016-BrowseTableModel::BrowseTableModel(QObject* parent, TrackCollection* pTrackCollection,
2017+BrowseTableModel::BrowseTableModel(QObject* parent,
2018+ TrackCollection* pTrackCollection,
2019 RecordingManager* pRecordingManager)
2020- : TrackModel(pTrackCollection->getDatabase(), // TrackCollections m_db (defaultConnection)
2021+ : TrackModel(pTrackCollection->getDatabase(),
2022 "mixxx.db.model.browse"),
2023 QStandardItemModel(parent),
2024 m_pTrackCollection(pTrackCollection),
2025- m_pRecordingManager(pRecordingManager) {
2026+ m_pRecordingManager(pRecordingManager) {
2027 QStringList header_data;
2028 header_data.insert(COLUMN_FILENAME, tr("Filename"));
2029 header_data.insert(COLUMN_ARTIST, tr("Artist"));
2030@@ -50,23 +51,24 @@
2031 addSearchColumn(COLUMN_COMMENT);
2032
2033 setHorizontalHeaderLabels(header_data);
2034- //register the QList<T> as a metatype since we use QueuedConnection below
2035- qRegisterMetaType< QList< QList<QStandardItem*> > >("QList< QList<QStandardItem*> >");
2036+ // register the QList<T> as a metatype since we use QueuedConnection below
2037+ qRegisterMetaType< QList< QList<QStandardItem*> > >(
2038+ "QList< QList<QStandardItem*> >");
2039 qRegisterMetaType<BrowseTableModel*>("BrowseTableModel*");
2040
2041 connect(BrowseThread::getInstance(), SIGNAL(clearModel(BrowseTableModel*)),
2042 this, SLOT(slotClear(BrowseTableModel*)),
2043 Qt::QueuedConnection);
2044
2045- connect(BrowseThread::getInstance(), SIGNAL(rowsAppended(const QList< QList<QStandardItem*> >&, BrowseTableModel*)),
2046- this, SLOT(slotInsert(const QList< QList<QStandardItem*> >&, BrowseTableModel*)),
2047- Qt::QueuedConnection);
2048-
2049+ connect(
2050+ BrowseThread::getInstance(),
2051+ SIGNAL(rowsAppended(const QList< QList<QStandardItem*> >&, BrowseTableModel*)),
2052+ this,
2053+ SLOT(slotInsert(const QList< QList<QStandardItem*> >&, BrowseTableModel*)),
2054+ Qt::QueuedConnection);
2055 }
2056
2057-BrowseTableModel::~BrowseTableModel()
2058-{
2059-
2060+BrowseTableModel::~BrowseTableModel() {
2061 }
2062
2063 const QList<int>& BrowseTableModel::searchColumns() const {
2064@@ -77,20 +79,19 @@
2065 m_searchColumns.push_back(index);
2066 }
2067
2068-void BrowseTableModel::setPath(QString absPath)
2069-{
2070+void BrowseTableModel::setPath(QString absPath) {
2071 m_current_path = absPath;
2072 BrowseThread::getInstance()->executePopulation(m_current_path, this);
2073-
2074 }
2075
2076-TrackPointer BrowseTableModel::getTrack(const QModelIndex& index) const
2077-{
2078+TrackPointer BrowseTableModel::getTrack(const QModelIndex& index) const {
2079 QString track_location = getTrackLocation(index);
2080- if(m_pRecordingManager->getRecordingLocation() == track_location) {
2081- QMessageBox::critical(0, tr("Mixxx Library"),tr("Could not load the following file because"
2082- " it is in use by Mixxx or another application.")
2083- + "\n" +track_location);
2084+ if (m_pRecordingManager->getRecordingLocation() == track_location) {
2085+ QMessageBox::critical(
2086+ 0, tr("Mixxx Library"),
2087+ tr("Could not load the following file because"
2088+ " it is in use by Mixxx or another application.")
2089+ + "\n" +track_location);
2090 return TrackPointer();
2091 }
2092
2093@@ -104,29 +105,27 @@
2094 return track_dao.getTrack(track_id);
2095 }
2096
2097-QString BrowseTableModel::getTrackLocation(const QModelIndex& index) const
2098-{
2099+QString BrowseTableModel::getTrackLocation(const QModelIndex& index) const {
2100 int row = index.row();
2101
2102 QModelIndex index2 = this->index(row, COLUMN_LOCATION);
2103 return data(index2).toString();
2104-
2105 }
2106
2107 int BrowseTableModel::getTrackId(const QModelIndex& index) const {
2108- Q_UNUSED(index);
2109- // We can't implement this as it stands.
2110+ Q_UNUSED(index);
2111+ // We can't implement this as it stands.
2112 return -1;
2113 }
2114
2115 const QLinkedList<int> BrowseTableModel::getTrackRows(int trackId) const {
2116- Q_UNUSED(trackId);
2117- // We can't implement this as it stands.
2118- return QLinkedList<int>();
2119+ Q_UNUSED(trackId);
2120+ // We can't implement this as it stands.
2121+ return QLinkedList<int>();
2122 }
2123
2124 void BrowseTableModel::search(const QString& searchText) {
2125- Q_UNUSED(searchText);
2126+ Q_UNUSED(searchText);
2127 }
2128
2129 const QString BrowseTableModel::currentSearch() const {
2130@@ -142,16 +141,14 @@
2131 }
2132
2133 void BrowseTableModel::moveTrack(const QModelIndex&, const QModelIndex&) {
2134-
2135 }
2136
2137 QItemDelegate* BrowseTableModel::delegateForColumn(const int) {
2138 return NULL;
2139 }
2140
2141-void BrowseTableModel::removeTrack(const QModelIndex& index)
2142-{
2143- if(!index.isValid()) {
2144+void BrowseTableModel::removeTrack(const QModelIndex& index) {
2145+ if (!index.isValid()) {
2146 return;
2147 }
2148 QStringList trackLocations;
2149@@ -159,8 +156,7 @@
2150 removeTracks(trackLocations);
2151 }
2152
2153-void BrowseTableModel::removeTracks(const QModelIndexList& indices)
2154-{
2155+void BrowseTableModel::removeTracks(const QModelIndexList& indices) {
2156 QStringList trackLocations;
2157 foreach (QModelIndex index, indices) {
2158 if (!index.isValid()) {
2159@@ -176,11 +172,12 @@
2160 return;
2161
2162 // Ask user if s/he is sure
2163- if (QMessageBox::question(NULL, tr("Mixxx Library"),
2164- tr("Warning: This will permanently delete the following files:")
2165- + "\n" + trackLocations.join("\n") + "\n" +
2166- tr("Are you sure you want to delete these files from your computer?"),
2167- QMessageBox::Yes, QMessageBox::Abort) == QMessageBox::Abort) {
2168+ if (QMessageBox::question(
2169+ NULL, tr("Mixxx Library"),
2170+ tr("Warning: This will permanently delete the following files:")
2171+ + "\n" + trackLocations.join("\n") + "\n" +
2172+ tr("Are you sure you want to delete these files from your computer?"),
2173+ QMessageBox::Yes, QMessageBox::Abort) == QMessageBox::Abort) {
2174 return;
2175 }
2176
2177@@ -191,8 +188,10 @@
2178 foreach (QString track_location, trackLocations) {
2179 // If track is in use or deletion fails, show an error message.
2180 if (isTrackInUse(track_location) || !QFile::remove(track_location)) {
2181- QMessageBox::critical(0, tr("Mixxx Library"),tr("Could not delete the following file because"
2182- " it is in use by Mixxx or another application:") + "\n" +track_location);
2183+ QMessageBox::critical(
2184+ 0, tr("Mixxx Library"),
2185+ tr("Could not delete the following file because"
2186+ " it is in use by Mixxx or another application:") + "\n" +track_location);
2187 continue;
2188 }
2189
2190@@ -213,20 +212,19 @@
2191 }
2192 }
2193
2194-bool BrowseTableModel::addTrack(const QModelIndex& index, QString location)
2195-{
2196+bool BrowseTableModel::addTrack(const QModelIndex& index, QString location) {
2197 Q_UNUSED(index);
2198 Q_UNUSED(location);
2199- return false;
2200+ return false;
2201 }
2202
2203 QMimeData* BrowseTableModel::mimeData(const QModelIndexList &indexes) const {
2204 QMimeData *mimeData = new QMimeData();
2205 QList<QUrl> urls;
2206
2207- //Ok, so the list of indexes we're given contains separates indexes for
2208- //each column, so even if only one row is selected, we'll have like 7 indexes.
2209- //We need to only count each row once:
2210+ // Ok, so the list of indexes we're given contains separates indexes for
2211+ // each column, so even if only one row is selected, we'll have like 7
2212+ // indexes. We need to only count each row once:
2213 QList<int> rows;
2214
2215 foreach (QModelIndex index, indexes) {
2216@@ -234,9 +232,9 @@
2217 if (!rows.contains(index.row())) {
2218 rows.push_back(index.row());
2219 QUrl url = QUrl::fromLocalFile(getTrackLocation(index));
2220- if (!url.isValid())
2221+ if (!url.isValid()) {
2222 qDebug() << "ERROR invalid url\n";
2223- else {
2224+ } else {
2225 urls.append(url);
2226 qDebug() << "Appending URL:" << url;
2227 }
2228@@ -247,22 +245,23 @@
2229 return mimeData;
2230 }
2231
2232-void BrowseTableModel::slotClear(BrowseTableModel* caller_object)
2233-{
2234- if(caller_object == this)
2235+void BrowseTableModel::slotClear(BrowseTableModel* caller_object) {
2236+ if (caller_object == this) {
2237 removeRows(0, rowCount());
2238+ }
2239 }
2240
2241-void BrowseTableModel::slotInsert(const QList< QList<QStandardItem*> >& rows, BrowseTableModel* caller_object) {
2242- //There exists more than one BrowseTableModel in Mixxx
2243- //We only want to receive items here, this object has 'ordered' by the BrowserThread (singleton)
2244- if(caller_object == this) {
2245+void BrowseTableModel::slotInsert(const QList< QList<QStandardItem*> >& rows,
2246+ BrowseTableModel* caller_object) {
2247+ // There exists more than one BrowseTableModel in Mixxx We only want to
2248+ // receive items here, this object has 'ordered' by the BrowserThread
2249+ // (singleton)
2250+ if (caller_object == this) {
2251 //qDebug() << "BrowseTableModel::slotInsert";
2252- for(int i=0; i < rows.size(); ++i) {
2253+ for (int i = 0; i < rows.size(); ++i) {
2254 appendRow(rows.at(i));
2255 }
2256 }
2257-
2258 }
2259
2260 TrackModel::CapabilitiesFlags BrowseTableModel::getCapabilities() const {
2261@@ -275,106 +274,108 @@
2262 | TRACKMODELCAPS_LOADTOSAMPLER;
2263 }
2264
2265-Qt::ItemFlags BrowseTableModel::flags(const QModelIndex &index) const{
2266-
2267+Qt::ItemFlags BrowseTableModel::flags(const QModelIndex &index) const {
2268 Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);
2269
2270- //Enable dragging songs from this data model to elsewhere (like the waveform
2271- //widget to load a track into a Player).
2272+ // Enable dragging songs from this data model to elsewhere (like the
2273+ // waveform widget to load a track into a Player).
2274 defaultFlags |= Qt::ItemIsDragEnabled;
2275
2276 QString track_location = getTrackLocation(index);
2277 int column = index.column();
2278
2279- if(isTrackInUse(track_location) ||
2280+ if (isTrackInUse(track_location) ||
2281 column == COLUMN_FILENAME ||
2282 column == COLUMN_BITRATE ||
2283 column == COLUMN_DURATION ||
2284 column == COLUMN_TYPE) {
2285 return defaultFlags;
2286- }
2287- else{
2288+ } else {
2289 return defaultFlags | Qt::ItemIsEditable;
2290 }
2291 }
2292
2293-bool BrowseTableModel::isTrackInUse(QString &track_location) const
2294-{
2295- int decks = ControlObject::getControl(ConfigKey("[Master]","num_decks"))->get();
2296- //check if file is loaded to a deck
2297- for(int i=1; i <= decks; ++i) {
2298- TrackPointer loaded_track = PlayerInfo::Instance().getTrackInfo(QString("[Channel%1]").arg(i));
2299- if(loaded_track && (loaded_track->getLocation() == track_location)) {
2300+bool BrowseTableModel::isTrackInUse(const QString &track_location) const {
2301+ int decks = ControlObject::getControl(
2302+ ConfigKey("[Master]", "num_decks"))->get();
2303+ // check if file is loaded to a deck
2304+ for (int i = 1; i <= decks; ++i) {
2305+ TrackPointer loaded_track = PlayerInfo::Instance().getTrackInfo(
2306+ QString("[Channel%1]").arg(i));
2307+ if (loaded_track && (loaded_track->getLocation() == track_location)) {
2308 return true;
2309 }
2310 }
2311
2312- if(m_pRecordingManager->getRecordingLocation() == track_location) {
2313+ if (m_pRecordingManager->getRecordingLocation() == track_location) {
2314 return true;
2315 }
2316
2317 return false;
2318 }
2319
2320-bool BrowseTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
2321-{
2322+bool BrowseTableModel::setData(const QModelIndex &index, const QVariant &value,
2323+ int role) {
2324 Q_UNUSED(role);
2325
2326- if(!index.isValid())
2327+ if (!index.isValid()) {
2328 return false;
2329+ }
2330 qDebug() << "BrowseTableModel::setData(" << index.data() << ")";
2331 int row = index.row();
2332 int col = index.column();
2333 QString track_location = getTrackLocation(index);
2334 AudioTagger tagger(track_location);
2335
2336- //set tagger information
2337- tagger.setArtist(this->index(row,COLUMN_ARTIST).data().toString());
2338- tagger.setTitle(this->index(row,COLUMN_TITLE).data().toString());
2339- tagger.setAlbum(this->index(row,COLUMN_ALBUM).data().toString());
2340- tagger.setKey(this->index(row,COLUMN_KEY).data().toString());
2341- tagger.setBpm(this->index(row,COLUMN_BPM).data().toString());
2342- tagger.setComment(this->index(row,COLUMN_COMMENT).data().toString());
2343- tagger.setTracknumber(this->index(row,COLUMN_TRACK_NUMBER).data().toString());
2344- tagger.setYear(this->index(row,COLUMN_YEAR).data().toString());
2345- tagger.setGenre(this->index(row,COLUMN_GENRE).data().toString());
2346- tagger.setComposer(this->index(row,COLUMN_COMPOSER).data().toString());
2347+ // set tagger information
2348+ tagger.setArtist(this->index(row, COLUMN_ARTIST).data().toString());
2349+ tagger.setTitle(this->index(row, COLUMN_TITLE).data().toString());
2350+ tagger.setAlbum(this->index(row, COLUMN_ALBUM).data().toString());
2351+ tagger.setKey(this->index(row, COLUMN_KEY).data().toString());
2352+ tagger.setBpm(this->index(row, COLUMN_BPM).data().toString());
2353+ tagger.setComment(this->index(row, COLUMN_COMMENT).data().toString());
2354+ tagger.setTracknumber(
2355+ this->index(row, COLUMN_TRACK_NUMBER).data().toString());
2356+ tagger.setYear(this->index(row, COLUMN_YEAR).data().toString());
2357+ tagger.setGenre(this->index(row, COLUMN_GENRE).data().toString());
2358+ tagger.setComposer(this->index(row, COLUMN_COMPOSER).data().toString());
2359
2360- //check if one the item were edited
2361- if(col == COLUMN_ARTIST) {
2362+ // check if one the item were edited
2363+ if (col == COLUMN_ARTIST) {
2364 tagger.setArtist(value.toString());
2365- } else if(col == COLUMN_TITLE) {
2366+ } else if (col == COLUMN_TITLE) {
2367 tagger.setTitle(value.toString());
2368- } else if(col == COLUMN_ALBUM) {
2369+ } else if (col == COLUMN_ALBUM) {
2370 tagger.setAlbum(value.toString());
2371- } else if(col == COLUMN_BPM) {
2372+ } else if (col == COLUMN_BPM) {
2373 tagger.setBpm(value.toString());
2374- } else if(col == COLUMN_KEY) {
2375+ } else if (col == COLUMN_KEY) {
2376 tagger.setKey(value.toString());
2377- } else if(col == COLUMN_TRACK_NUMBER) {
2378+ } else if (col == COLUMN_TRACK_NUMBER) {
2379 tagger.setTracknumber(value.toString());
2380- } else if(col == COLUMN_COMMENT) {
2381+ } else if (col == COLUMN_COMMENT) {
2382 tagger.setComment(value.toString());
2383- } else if(col == COLUMN_GENRE) {
2384+ } else if (col == COLUMN_GENRE) {
2385 tagger.setGenre(value.toString());
2386- } else if(col == COLUMN_COMPOSER) {
2387+ } else if (col == COLUMN_COMPOSER) {
2388 tagger.setComposer(value.toString());
2389- } else if(col == COLUMN_YEAR) {
2390+ } else if (col == COLUMN_YEAR) {
2391 tagger.setYear(value.toString());
2392 }
2393
2394
2395 QStandardItem* item = itemFromIndex(index);
2396- if(tagger.save()) {
2397- //Modify underlying interalPointer object
2398+ if (tagger.save()) {
2399+ // Modify underlying interalPointer object
2400 item->setText(value.toString());
2401 return true;
2402- }
2403- else {
2404- //reset to old value in error
2405+ } else {
2406+ // reset to old value in error
2407 item->setText(index.data().toString());
2408- QMessageBox::critical(0, tr("Mixxx Library"),tr("Could not update file metadata.")
2409- + "\n" +track_location);
2410+ QMessageBox::critical(
2411+ 0, tr("Mixxx Library"),
2412+ tr("Could not update file metadata.")
2413+ + "\n" +track_location);
2414 return false;
2415 }
2416 }
2417
2418=== modified file 'mixxx/src/library/browse/browsetablemodel.h'
2419--- mixxx/src/library/browse/browsetablemodel.h 2012-01-07 05:48:41 +0000
2420+++ mixxx/src/library/browse/browsetablemodel.h 2012-03-12 04:06:20 +0000
2421@@ -66,7 +66,7 @@
2422 void removeTracks(QStringList trackLocations);
2423
2424 void addSearchColumn(int index);
2425- bool isTrackInUse(QString& file) const;
2426+ bool isTrackInUse(const QString& file) const;
2427 QList<int> m_searchColumns;
2428 QString m_current_path;
2429 TrackCollection* m_pTrackCollection;
2430
2431=== modified file 'mixxx/src/library/dao/cratedao.h'
2432--- mixxx/src/library/dao/cratedao.h 2011-10-21 00:42:23 +0000
2433+++ mixxx/src/library/dao/cratedao.h 2012-03-12 04:06:20 +0000
2434@@ -47,6 +47,8 @@
2435 void changed(int crateId);
2436 void trackAdded(int crateId, int trackId);
2437 void trackRemoved(int crateId, int trackId);
2438+ void renamed(int crateId);
2439+ void lockChanged(int crateId);
2440
2441 private:
2442 QSqlDatabase& m_database;
2443
2444=== modified file 'mixxx/src/widget/wtracktableview.cpp'
2445--- mixxx/src/widget/wtracktableview.cpp 2011-12-14 17:22:49 +0000
2446+++ mixxx/src/widget/wtracktableview.cpp 2012-03-12 04:06:20 +0000
2447@@ -82,6 +82,7 @@
2448
2449 delete m_pReloadMetadataAct;
2450 delete m_pAutoDJAct;
2451+ delete m_pAutoDJTopAct;
2452 delete m_pRemoveAct;
2453 delete m_pPropertiesAct;
2454 delete m_pMenu;
2455@@ -241,7 +242,8 @@
2456 void WTrackTableView::disableSorting() {
2457 // We have to manually do this because setSortingEnabled(false) does not
2458 // properly disconnect the signals for some reason.
2459- disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
2460+ disconnect(horizontalHeader(),
2461+ SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
2462 this, SLOT(doSortByColumn(int)));
2463 horizontalHeader()->setSortIndicatorShown(false);
2464 }
2465@@ -250,17 +252,23 @@
2466 Q_ASSERT(m_pMenu);
2467 Q_ASSERT(m_pSamplerMenu);
2468
2469- m_pRemoveAct = new QAction(tr("Remove"),this);
2470+ m_pRemoveAct = new QAction(tr("Remove"), this);
2471 connect(m_pRemoveAct, SIGNAL(triggered()), this, SLOT(slotRemove()));
2472
2473 m_pPropertiesAct = new QAction(tr("Properties..."), this);
2474- connect(m_pPropertiesAct, SIGNAL(triggered()), this, SLOT(slotShowTrackInfo()));
2475+ connect(m_pPropertiesAct, SIGNAL(triggered()),
2476+ this, SLOT(slotShowTrackInfo()));
2477
2478- m_pAutoDJAct = new QAction(tr("Add to Auto DJ Queue"),this);
2479+ m_pAutoDJAct = new QAction(tr("Add to Auto-DJ Queue (bottom)"), this);
2480 connect(m_pAutoDJAct, SIGNAL(triggered()), this, SLOT(slotSendToAutoDJ()));
2481
2482+ m_pAutoDJTopAct = new QAction(tr("Add to Auto-DJ Queue (top)"), this);
2483+ connect(m_pAutoDJTopAct, SIGNAL(triggered()),
2484+ this, SLOT(slotSendToAutoDJTop()));
2485+
2486 m_pReloadMetadataAct = new QAction(tr("Reload Track Metadata"), this);
2487- connect(m_pReloadMetadataAct, SIGNAL(triggered()), this, SLOT(slotReloadTrackMetadata()));
2488+ connect(m_pReloadMetadataAct, SIGNAL(triggered()),
2489+ this, SLOT(slotReloadTrackMetadata()));
2490 }
2491
2492 void WTrackTableView::slotMouseDoubleClicked(const QModelIndex &index) {
2493@@ -345,8 +353,7 @@
2494 m_pTrackInfo->show();
2495 }
2496
2497-void WTrackTableView::contextMenuEvent(QContextMenuEvent * event)
2498-{
2499+void WTrackTableView::contextMenuEvent(QContextMenuEvent* event) {
2500 QModelIndexList indices = selectionModel()->selectedRows();
2501
2502 // Gray out some stuff if multiple songs were selected.
2503@@ -356,6 +363,7 @@
2504
2505 if (modelHasCapabilities(TrackModel::TRACKMODELCAPS_ADDTOAUTODJ)) {
2506 m_pMenu->addAction(m_pAutoDJAct);
2507+ m_pMenu->addAction(m_pAutoDJTopAct);
2508 m_pMenu->addSeparator();
2509 }
2510
2511@@ -800,6 +808,15 @@
2512 }
2513
2514 void WTrackTableView::slotSendToAutoDJ() {
2515+ // append to auto DJ
2516+ sendToAutoDJ(false); // bTop = false
2517+}
2518+
2519+void WTrackTableView::slotSendToAutoDJTop() {
2520+ sendToAutoDJ(true); // bTop = true
2521+}
2522+
2523+void WTrackTableView::sendToAutoDJ(bool bTop) {
2524 if (!modelHasCapabilities(TrackModel::TRACKMODELCAPS_ADDTOAUTODJ)) {
2525 return;
2526 }
2527@@ -819,7 +836,15 @@
2528 (pTrack = trackModel->getTrack(index))) {
2529 int iTrackId = pTrack->getId();
2530 if (iTrackId != -1) {
2531- playlistDao.appendTrackToPlaylist(iTrackId, iAutoDJPlaylistId);
2532+ if (bTop) {
2533+ // Load track to position two because position one is
2534+ // already loaded to the player
2535+ playlistDao.insertTrackIntoPlaylist(iTrackId,
2536+ iAutoDJPlaylistId, 2);
2537+ } else {
2538+ playlistDao.appendTrackToPlaylist(
2539+ iTrackId, iAutoDJPlaylistId);
2540+ }
2541 }
2542 }
2543 }
2544
2545=== modified file 'mixxx/src/widget/wtracktableview.h'
2546--- mixxx/src/widget/wtracktableview.h 2011-10-14 03:58:14 +0000
2547+++ mixxx/src/widget/wtracktableview.h 2012-03-12 04:06:20 +0000
2548@@ -19,10 +19,9 @@
2549 const QString LIBRARY_CONFIGVALUE = "[Library]"; /** ConfigValue "value" (wtf) for library stuff */
2550
2551
2552-class WTrackTableView : public WLibraryTableView
2553-{
2554+class WTrackTableView : public WLibraryTableView {
2555 Q_OBJECT
2556- public:
2557+ public:
2558 WTrackTableView(QWidget* parent, ConfigObject<ConfigValue>* pConfig,
2559 TrackCollection* pTrackCollection);
2560 virtual ~WTrackTableView();
2561@@ -46,6 +45,7 @@
2562 void slotNextTrackInfo();
2563 void slotPrevTrackInfo();
2564 void slotSendToAutoDJ();
2565+ void slotSendToAutoDJTop();
2566 void slotReloadTrackMetadata();
2567 void addSelectionToPlaylist(int iPlaylistId);
2568 void addSelectionToCrate(int iCrateId);
2569@@ -53,6 +53,7 @@
2570 void doSortByColumn(int headerSection);
2571
2572 private:
2573+ void sendToAutoDJ(bool bTop);
2574 void showTrackInfo(QModelIndex index);
2575 void createActions();
2576 void dragMoveEvent(QDragMoveEvent * event);
2577@@ -89,6 +90,7 @@
2578
2579 // Send to Auto-DJ Action
2580 QAction *m_pAutoDJAct;
2581+ QAction *m_pAutoDJTopAct;
2582
2583 // Remove from table
2584 QAction *m_pRemoveAct;