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
=== added directory 'mixxx/res/images/autodj'
=== added file 'mixxx/res/images/autodj/bottom.svg'
--- mixxx/res/images/autodj/bottom.svg 1970-01-01 00:00:00 +0000
+++ mixxx/res/images/autodj/bottom.svg 2012-03-12 04:06:20 +0000
@@ -0,0 +1,137 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!-- Created with Inkscape (http://www.inkscape.org/) -->
3<svg
4 xmlns:dc="http://purl.org/dc/elements/1.1/"
5 xmlns:cc="http://creativecommons.org/ns#"
6 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
7 xmlns:svg="http://www.w3.org/2000/svg"
8 xmlns="http://www.w3.org/2000/svg"
9 xmlns:xlink="http://www.w3.org/1999/xlink"
10 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
11 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
12 width="48px"
13 height="48px"
14 id="svg4289"
15 sodipodi:version="0.32"
16 inkscape:version="0.46"
17 sodipodi:docbase="/home/lapo/Icone/cvs/gnome-icon-theme/scalable/categories"
18 sodipodi:docname="bottom.svg"
19 inkscape:output_extension="org.inkscape.output.svg.inkscape">
20 <defs
21 id="defs4291">
22 <linearGradient
23 id="linearGradient3155"
24 inkscape:collect="always">
25 <stop
26 id="stop3157"
27 offset="0"
28 style="stop-color:#ffb584;stop-opacity:1;" />
29 <stop
30 id="stop3159"
31 offset="1"
32 style="stop-color:#ffb584;stop-opacity:0;" />
33 </linearGradient>
34 <linearGradient
35 inkscape:collect="always"
36 xlink:href="#linearGradient3155"
37 id="linearGradient3273"
38 gradientUnits="userSpaceOnUse"
39 gradientTransform="matrix(0.1532521,0,0,0.1530054,-25.916429,-53.611392)"
40 x1="325.71429"
41 y1="369.50507"
42 x2="325.71429"
43 y2="546.64789" />
44 </defs>
45 <sodipodi:namedview
46 id="base"
47 pagecolor="#ffffff"
48 bordercolor="#666"
49 borderopacity="0.31372549"
50 inkscape:pageopacity="0.0"
51 inkscape:pageshadow="2"
52 inkscape:zoom="5.656854"
53 inkscape:cx="25.963489"
54 inkscape:cy="20.551712"
55 inkscape:current-layer="layer1"
56 showgrid="true"
57 inkscape:grid-bbox="true"
58 inkscape:document-units="px"
59 inkscape:window-width="1019"
60 inkscape:window-height="732"
61 inkscape:window-x="259"
62 inkscape:window-y="19"
63 inkscape:showpageshadow="false" />
64 <metadata
65 id="metadata4294">
66 <rdf:RDF>
67 <cc:Work
68 rdf:about="">
69 <dc:format>image/svg+xml</dc:format>
70 <dc:type
71 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
72 <dc:title>System Preferences</dc:title>
73 <dc:creator>
74 <cc:Agent>
75 <dc:title>Andreas Nilsson</dc:title>
76 </cc:Agent>
77 </dc:creator>
78 <dc:subject>
79 <rdf:Bag>
80 <rdf:li>category</rdf:li>
81 <rdf:li>system</rdf:li>
82 <rdf:li>preferences</rdf:li>
83 <rdf:li>settings</rdf:li>
84 <rdf:li>control center</rdf:li>
85 </rdf:Bag>
86 </dc:subject>
87 <dc:contributor>
88 <cc:Agent>
89 <dc:title>Jakub Steiner</dc:title>
90 </cc:Agent>
91 </dc:contributor>
92 <cc:license
93 rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
94 </cc:Work>
95 <cc:License
96 rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
97 <cc:permits
98 rdf:resource="http://web.resource.org/cc/Reproduction" />
99 <cc:permits
100 rdf:resource="http://web.resource.org/cc/Distribution" />
101 <cc:requires
102 rdf:resource="http://web.resource.org/cc/Notice" />
103 <cc:permits
104 rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
105 <cc:requires
106 rdf:resource="http://web.resource.org/cc/ShareAlike" />
107 <cc:requires
108 rdf:resource="http://web.resource.org/cc/SourceCode" />
109 </cc:License>
110 </rdf:RDF>
111 </metadata>
112 <g
113 id="layer1"
114 inkscape:label="Layer 1"
115 inkscape:groupmode="layer">
116 <g
117 id="g2453"
118 inkscape:label="Calque 1"
119 transform="matrix(0.1337942,0,0,0.1337942,-18.472238,-41.04701)" />
120 <path
121 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"
122 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"
123 id="path4348"
124 sodipodi:nodetypes="cccccccc" />
125 <rect
126 y="39.555557"
127 x="6.75"
128 height="4.4444442"
129 width="34.499985"
130 id="rect4242"
131 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" />
132 <path
133 style="fill:url(#linearGradient3273);fill-opacity:1"
134 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"
135 id="path3261" />
136 </g>
137</svg>
0138
=== added file 'mixxx/res/images/autodj/media-playlist-shuffle.svg'
--- mixxx/res/images/autodj/media-playlist-shuffle.svg 1970-01-01 00:00:00 +0000
+++ mixxx/res/images/autodj/media-playlist-shuffle.svg 2012-03-12 04:06:20 +0000
@@ -0,0 +1,214 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!-- Created with Inkscape (http://www.inkscape.org/) -->
3
4<svg
5 xmlns:dc="http://purl.org/dc/elements/1.1/"
6 xmlns:cc="http://creativecommons.org/ns#"
7 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8 xmlns:svg="http://www.w3.org/2000/svg"
9 xmlns="http://www.w3.org/2000/svg"
10 xmlns:xlink="http://www.w3.org/1999/xlink"
11 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
12 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13 width="48"
14 height="48"
15 id="svg7854"
16 sodipodi:version="0.32"
17 inkscape:version="0.47 r22583"
18 version="1.0"
19 sodipodi:docname="media-playlist-shuffle.svg"
20 inkscape:output_extension="org.inkscape.output.svg.inkscape"
21 inkscape:export-filename="/home/lapo/Icone/gnome-icon-theme/32x32/status/media-playlist-repeat.png"
22 inkscape:export-xdpi="90"
23 inkscape:export-ydpi="90">
24 <defs
25 id="defs7856">
26 <linearGradient
27 gradientUnits="userSpaceOnUse"
28 y2="21.132059"
29 x2="22.892584"
30 y1="0.90414524"
31 x1="22.892584"
32 id="linearGradient3178"
33 xlink:href="#linearGradient3172"
34 inkscape:collect="always" />
35 <linearGradient
36 id="linearGradient3172">
37 <stop
38 id="stop3174"
39 offset="0"
40 style="stop-color:#ffb584;stop-opacity:1;" />
41 <stop
42 id="stop3176"
43 offset="1"
44 style="stop-color:#ffb584;stop-opacity:0;" />
45 </linearGradient>
46 <linearGradient
47 inkscape:collect="always"
48 xlink:href="#linearGradient3172"
49 id="linearGradient3747"
50 gradientUnits="userSpaceOnUse"
51 x1="22.892584"
52 y1="0.90414524"
53 x2="22.892584"
54 y2="21.132059" />
55 <linearGradient
56 inkscape:collect="always"
57 xlink:href="#linearGradient3172"
58 id="linearGradient3752"
59 gradientUnits="userSpaceOnUse"
60 x1="22.892584"
61 y1="0.90414524"
62 x2="22.892584"
63 y2="21.132059"
64 gradientTransform="matrix(0.644962,0,0,-1.1832362,59.235153,43.983663)" />
65 <linearGradient
66 inkscape:collect="always"
67 xlink:href="#linearGradient3172"
68 id="linearGradient3755"
69 gradientUnits="userSpaceOnUse"
70 gradientTransform="matrix(0.644962,0,0,1.1832362,9.235153,4.016337)"
71 x1="22.892584"
72 y1="0.90414524"
73 x2="22.892584"
74 y2="21.132059" />
75 </defs>
76 <sodipodi:namedview
77 id="base"
78 pagecolor="#ffffff"
79 bordercolor="#afafaf"
80 borderopacity="1"
81 gridtolerance="15.1"
82 guidetolerance="10"
83 objecttolerance="10"
84 inkscape:pageopacity="0"
85 inkscape:pageshadow="2"
86 inkscape:zoom="8"
87 inkscape:cx="20.022534"
88 inkscape:cy="20.71947"
89 inkscape:document-units="px"
90 inkscape:current-layer="layer1"
91 width="48px"
92 height="48px"
93 inkscape:showpageshadow="false"
94 inkscape:window-width="872"
95 inkscape:window-height="723"
96 inkscape:window-x="406"
97 inkscape:window-y="21"
98 showgrid="false"
99 inkscape:grid-points="false"
100 showborder="true"
101 showguides="false"
102 inkscape:guide-bbox="false"
103 inkscape:grid-bbox="true"
104 inkscape:object-paths="false"
105 inkscape:window-maximized="0">
106 <sodipodi:guide
107 orientation="horizontal"
108 position="8.6620581"
109 id="guide7377" />
110 <sodipodi:guide
111 orientation="horizontal"
112 position="6"
113 id="guide7379" />
114 <sodipodi:guide
115 orientation="horizontal"
116 position="36.062446"
117 id="guide7492" />
118 <sodipodi:guide
119 orientation="horizontal"
120 position="51"
121 id="guide7046" />
122 <sodipodi:guide
123 orientation="horizontal"
124 position="-17.5"
125 id="guide7233" />
126 <sodipodi:guide
127 orientation="horizontal"
128 position="-29"
129 id="guide7235" />
130 <sodipodi:guide
131 orientation="horizontal"
132 position="44.547727"
133 id="guide6795" />
134 <sodipodi:guide
135 orientation="horizontal"
136 position="16.970563"
137 id="guide6797" />
138 <sodipodi:guide
139 orientation="horizontal"
140 position="23.511301"
141 id="guide6914" />
142 <inkscape:grid
143 id="GridFromPre046Settings"
144 type="xygrid"
145 originx="0px"
146 originy="0px"
147 spacingx="0.5px"
148 spacingy="0.5px"
149 color="#0000ff"
150 empcolor="#0000ff"
151 opacity="0.2"
152 empopacity="0.4"
153 empspacing="2" />
154 </sodipodi:namedview>
155 <metadata
156 id="metadata7859">
157 <rdf:RDF>
158 <cc:Work
159 rdf:about="">
160 <dc:format>image/svg+xml</dc:format>
161 <dc:type
162 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
163 <dc:creator>
164 <cc:Agent>
165 <dc:title>Lapo Calamandrei</dc:title>
166 </cc:Agent>
167 </dc:creator>
168 <dc:source />
169 <cc:license
170 rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
171 <dc:title></dc:title>
172 <dc:subject>
173 <rdf:Bag />
174 </dc:subject>
175 </cc:Work>
176 <cc:License
177 rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
178 <cc:permits
179 rdf:resource="http://web.resource.org/cc/Reproduction" />
180 <cc:permits
181 rdf:resource="http://web.resource.org/cc/Distribution" />
182 <cc:requires
183 rdf:resource="http://web.resource.org/cc/Notice" />
184 <cc:permits
185 rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
186 <cc:requires
187 rdf:resource="http://web.resource.org/cc/ShareAlike" />
188 <cc:requires
189 rdf:resource="http://web.resource.org/cc/SourceCode" />
190 </cc:License>
191 </rdf:RDF>
192 </metadata>
193 <g
194 inkscape:label="Layer 1"
195 inkscape:groupmode="layer"
196 id="layer1">
197 <path
198 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"
199 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"
200 id="path6784" />
201 <path
202 style="fill:url(#linearGradient3755);fill-opacity:1;stroke:none"
203 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"
204 id="path3741" />
205 <g
206 transform="matrix(0.1337942,0,0,-0.1337942,31.527762,89.04701)"
207 inkscape:label="Calque 1"
208 id="g3743" />
209 <g
210 transform="matrix(0.1672428,0,0,-0.1672428,38.442916,104.62323)"
211 inkscape:label="Calque 1"
212 id="g3745" />
213 </g>
214</svg>
0215
=== added file 'mixxx/res/images/autodj/stock_mail-send-receive.svg'
--- mixxx/res/images/autodj/stock_mail-send-receive.svg 1970-01-01 00:00:00 +0000
+++ mixxx/res/images/autodj/stock_mail-send-receive.svg 2012-03-12 04:06:20 +0000
@@ -0,0 +1,87 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!-- Created with Inkscape (http://www.inkscape.org/) -->
3
4<svg
5 xmlns:dc="http://purl.org/dc/elements/1.1/"
6 xmlns:cc="http://creativecommons.org/ns#"
7 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8 xmlns:svg="http://www.w3.org/2000/svg"
9 xmlns="http://www.w3.org/2000/svg"
10 xmlns:xlink="http://www.w3.org/1999/xlink"
11 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
12 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13 width="48px"
14 height="48px"
15 id="svg3787"
16 version="1.1"
17 inkscape:version="0.47 r22583"
18 sodipodi:docname="Nouveau document 4">
19 <defs
20 id="defs3789">
21 <linearGradient
22 inkscape:collect="always"
23 xlink:href="#linearGradient3172"
24 id="linearGradient3767"
25 gradientUnits="userSpaceOnUse"
26 gradientTransform="matrix(0.644962,0,0,1.1832362,9.235153,4.016337)"
27 x1="22.892584"
28 y1="0.90414524"
29 x2="22.892584"
30 y2="21.132059" />
31 <linearGradient
32 id="linearGradient3172">
33 <stop
34 id="stop3174"
35 offset="0"
36 style="stop-color:#ffb584;stop-opacity:1;" />
37 <stop
38 id="stop3176"
39 offset="1"
40 style="stop-color:#ffb584;stop-opacity:0;" />
41 </linearGradient>
42 </defs>
43 <sodipodi:namedview
44 id="base"
45 pagecolor="#ffffff"
46 bordercolor="#666666"
47 borderopacity="1.0"
48 inkscape:pageopacity="0.0"
49 inkscape:pageshadow="2"
50 inkscape:zoom="7"
51 inkscape:cx="24"
52 inkscape:cy="24"
53 inkscape:current-layer="layer1"
54 showgrid="true"
55 inkscape:grid-bbox="true"
56 inkscape:document-units="px"
57 inkscape:window-width="596"
58 inkscape:window-height="502"
59 inkscape:window-x="768"
60 inkscape:window-y="24"
61 inkscape:window-maximized="0" />
62 <metadata
63 id="metadata3792">
64 <rdf:RDF>
65 <cc:Work
66 rdf:about="">
67 <dc:format>image/svg+xml</dc:format>
68 <dc:type
69 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
70 <dc:title></dc:title>
71 </cc:Work>
72 </rdf:RDF>
73 </metadata>
74 <g
75 id="layer1"
76 inkscape:label="Layer 1"
77 inkscape:groupmode="layer">
78 <path
79 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"
80 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"
81 id="path4360" />
82 <path
83 style="fill:url(#linearGradient3767);fill-opacity:1;stroke:none"
84 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"
85 id="path3753" />
86 </g>
87</svg>
088
=== modified file 'mixxx/res/mixxx.qrc'
--- mixxx/res/mixxx.qrc 2011-12-22 18:43:09 +0000
+++ mixxx/res/mixxx.qrc 2012-03-12 04:06:20 +0000
@@ -1,5 +1,8 @@
1<RCC>1<RCC>
2 <qresource prefix="/">2 <qresource prefix="/">
3 <file>images/autodj/media-playlist-shuffle.svg</file>
4 <file>images/autodj/stock_mail-send-receive.svg</file>
5 <file>images/autodj/bottom.svg</file>
3 <file>html/crates.html</file>6 <file>html/crates.html</file>
4 <file>html/playlists.html</file>7 <file>html/playlists.html</file>
5 <file>images/mixxx-icon.png</file>8 <file>images/mixxx-icon.png</file>
69
=== modified file 'mixxx/src/dlgautodj.cpp'
--- mixxx/src/dlgautodj.cpp 2011-11-30 06:19:47 +0000
+++ mixxx/src/dlgautodj.cpp 2012-03-12 04:06:20 +0000
@@ -1,28 +1,38 @@
1#include <QSqlTableModel>1#include <QSqlTableModel>
2#include "widget/wwidget.h"2
3#include "widget/wskincolor.h"3#include "dlgautodj.h"
4#include "widget/wtracktableview.h"4
5#include "controlobject.h"5#include "controlobject.h"
6#include "controlobjectthreadmain.h"6#include "controlobjectthreadmain.h"
7#include "library/playlisttablemodel.h"
7#include "library/trackcollection.h"8#include "library/trackcollection.h"
8#include "library/playlisttablemodel.h"9#include "playerinfo.h"
9#include "dlgautodj.h"10#include "widget/wskincolor.h"
11#include "widget/wtracktableview.h"
12#include "widget/wwidget.h"
1013
14#define CONFIG_KEY "[Auto DJ]"
15const char* kTransitionPreferenceName = "Transition";
16const int kTransitionPreferenceDefault = 10;
1117
12DlgAutoDJ::DlgAutoDJ(QWidget* parent, ConfigObject<ConfigValue>* pConfig,18DlgAutoDJ::DlgAutoDJ(QWidget* parent, ConfigObject<ConfigValue>* pConfig,
13 TrackCollection* pTrackCollection, MixxxKeyboard* pKeyboard)19 TrackCollection* pTrackCollection,
14 : QWidget(parent), Ui::DlgAutoDJ(), m_playlistDao(pTrackCollection->getPlaylistDAO())20 MixxxKeyboard* pKeyboard)
15{21 : QWidget(parent),
22 Ui::DlgAutoDJ(),
23 m_pConfig(pConfig),
24 m_pTrackCollection(pTrackCollection),
25 m_pTrackTableView(
26 new WTrackTableView(this, pConfig, m_pTrackCollection)),
27 m_playlistDao(pTrackCollection->getPlaylistDAO()),
28 m_bAutoDJEnabled(false),
29 m_bFadeNow(false),
30 m_eState(ADJ_IDLE),
31 m_posThreshold1(1.0f),
32 m_posThreshold2(1.0f) {
16 setupUi(this);33 setupUi(this);
1734
18 m_pConfig = pConfig;
19 m_pTrackCollection = pTrackCollection;
20 m_bAutoDJEnabled = false;
21 m_bPlayer1Primed = false;
22 m_bPlayer2Primed = false;
23 m_pTrackTableView = new WTrackTableView(this, pConfig, m_pTrackCollection);
24 m_pTrackTableView->installEventFilter(pKeyboard);35 m_pTrackTableView->installEventFilter(pKeyboard);
25
26 connect(m_pTrackTableView, SIGNAL(loadTrack(TrackPointer)),36 connect(m_pTrackTableView, SIGNAL(loadTrack(TrackPointer)),
27 this, SIGNAL(loadTrack(TrackPointer)));37 this, SIGNAL(loadTrack(TrackPointer)));
28 connect(m_pTrackTableView, SIGNAL(loadTrackToPlayer(TrackPointer, QString)),38 connect(m_pTrackTableView, SIGNAL(loadTrackToPlayer(TrackPointer, QString)),
@@ -34,8 +44,8 @@
34 m_pTrackTablePlaceholder->hide();44 m_pTrackTablePlaceholder->hide();
35 box->insertWidget(1, m_pTrackTableView);45 box->insertWidget(1, m_pTrackTableView);
3646
37 m_pAutoDJTableModel = new PlaylistTableModel(this, pTrackCollection,47 m_pAutoDJTableModel = new PlaylistTableModel(this, pTrackCollection,
38 "mixxx.db.model.autodj");48 "mixxx.db.model.autodj");
39 int playlistId = m_playlistDao.getPlaylistIdFromName(AUTODJ_TABLE);49 int playlistId = m_playlistDao.getPlaylistIdFromName(AUTODJ_TABLE);
40 if (playlistId < 0) {50 if (playlistId < 0) {
41 m_playlistDao.createPlaylist(AUTODJ_TABLE, true);51 m_playlistDao.createPlaylist(AUTODJ_TABLE, true);
@@ -44,7 +54,7 @@
44 m_pAutoDJTableModel->setPlaylist(playlistId);54 m_pAutoDJTableModel->setPlaylist(playlistId);
45 m_pTrackTableView->loadTrackModel(m_pAutoDJTableModel);55 m_pTrackTableView->loadTrackModel(m_pAutoDJTableModel);
4656
47 //Override some playlist-view properties:57 // Override some playlist-view properties:
4858
49 // Do not set this because it disables auto-scrolling59 // Do not set this because it disables auto-scrolling
50 //m_pTrackTableView->setDragDropMode(QAbstractItemView::InternalMove);60 //m_pTrackTableView->setDragDropMode(QAbstractItemView::InternalMove);
@@ -55,43 +65,65 @@
55 connect(pushButtonShuffle, SIGNAL(clicked(bool)),65 connect(pushButtonShuffle, SIGNAL(clicked(bool)),
56 this, SLOT(shufflePlaylist(bool)));66 this, SLOT(shufflePlaylist(bool)));
5767
68 connect(pushButtonSkipNext, SIGNAL(clicked(bool)),
69 this, SLOT(skipNext(bool)));
70
71 connect(pushButtonFadeNow, SIGNAL(clicked(bool)),
72 this, SLOT(fadeNow(bool)));
73
74 connect(spinBoxTransition, SIGNAL(valueChanged(int)),
75 this, SLOT(transitionValueChanged(int)));
76
58 connect(pushButtonAutoDJ, SIGNAL(toggled(bool)),77 connect(pushButtonAutoDJ, SIGNAL(toggled(bool)),
59 this, SLOT(toggleAutoDJ(bool))); _blah;78 this, SLOT(toggleAutoDJ(bool))); _blah;
6079
80 // playposition is from -0.14 to + 1.14
61 m_pCOPlayPos1 = new ControlObjectThreadMain(81 m_pCOPlayPos1 = new ControlObjectThreadMain(
62 ControlObject::getControl(ConfigKey("[Channel1]", "playposition")));82 ControlObject::getControl(ConfigKey("[Channel1]", "playposition")));
63 m_pCOPlayPos2 = new ControlObjectThreadMain(83 m_pCOPlayPos2 = new ControlObjectThreadMain(
64 ControlObject::getControl(ConfigKey("[Channel2]", "playposition")));84 ControlObject::getControl(ConfigKey("[Channel2]", "playposition")));
65 m_pCOPlay1 = new ControlObjectThreadMain(85 m_pCOPlay1 = new ControlObjectThreadMain(
66 ControlObject::getControl(ConfigKey("[Channel1]", "play")));86 ControlObject::getControl(ConfigKey("[Channel1]", "play")));
67 m_pCOPlay2 = new ControlObjectThreadMain(87 m_pCOPlay2 = new ControlObjectThreadMain(
68 ControlObject::getControl(ConfigKey("[Channel2]", "play")));88 ControlObject::getControl(ConfigKey("[Channel2]", "play")));
89 m_pCOPlay1Fb = new ControlObjectThreadMain(
90 ControlObject::getControl(ConfigKey("[Channel1]", "play")));
91 m_pCOPlay2Fb = new ControlObjectThreadMain(
92 ControlObject::getControl(ConfigKey("[Channel2]", "play")));
69 m_pCORepeat1 = new ControlObjectThreadMain(93 m_pCORepeat1 = new ControlObjectThreadMain(
70 ControlObject::getControl(ConfigKey("[Channel1]", "repeat")));94 ControlObject::getControl(ConfigKey("[Channel1]", "repeat")));
71 m_pCORepeat2 = new ControlObjectThreadMain(95 m_pCORepeat2 = new ControlObjectThreadMain(
72 ControlObject::getControl(ConfigKey("[Channel2]", "repeat")));96 ControlObject::getControl(ConfigKey("[Channel2]", "repeat")));
73 m_pCOCrossfader = new ControlObjectThreadMain(97 m_pCOCrossfader = new ControlObjectThreadMain(
74 ControlObject::getControl(ConfigKey("[Master]", "crossfader")));98 ControlObject::getControl(ConfigKey("[Master]", "crossfader")));
99
100 QString str_autoDjTransition = m_pConfig->getValueString(
101 ConfigKey(CONFIG_KEY, kTransitionPreferenceName));
102 if (str_autoDjTransition.isEmpty()) {
103 spinBoxTransition->setValue(kTransitionPreferenceDefault);
104 } else {
105 spinBoxTransition->setValue(str_autoDjTransition.toInt());
106 }
75}107}
76108
77DlgAutoDJ::~DlgAutoDJ()109DlgAutoDJ::~DlgAutoDJ() {
78{
79 delete m_pCOPlayPos1;110 delete m_pCOPlayPos1;
80 delete m_pCOPlayPos2;111 delete m_pCOPlayPos2;
81 delete m_pCOPlay1;112 delete m_pCOPlay1;
82 delete m_pCOPlay2;113 delete m_pCOPlay2;
114 delete m_pCOPlay1Fb;
115 delete m_pCOPlay2Fb;
116 delete m_pCORepeat1;
83 delete m_pCORepeat2;117 delete m_pCORepeat2;
84 delete m_pCOCrossfader;118 delete m_pCOCrossfader;
119 delete m_pAutoDJTableModel;
85}120}
86121
87void DlgAutoDJ::onShow()122void DlgAutoDJ::onShow() {
88{
89 m_pAutoDJTableModel->select();123 m_pAutoDJTableModel->select();
90}124}
91125
92void DlgAutoDJ::setup(QDomNode node)126void DlgAutoDJ::setup(QDomNode node) {
93{
94
95 QPalette pal = palette();127 QPalette pal = palette();
96128
97 // Row colors129 // Row colors
@@ -108,9 +140,6 @@
108 // the future this should be configurable from the skin with this as the140 // the future this should be configurable from the skin with this as the
109 // fallback option141 // fallback option
110 QColor text(255 - r1.red(), 255 - r1.green(), 255 - r1.blue());142 QColor text(255 - r1.red(), 255 - r1.green(), 255 - r1.blue());
111
112 //setAlternatingRowColors ( true );
113
114 QColor fgColor;143 QColor fgColor;
115 fgColor.setNamedColor(WWidget::selectNodeQString(node, "FgColor"));144 fgColor.setNamedColor(WWidget::selectNodeQString(node, "FgColor"));
116 fgColor = WSkinColor::getCorrectColor(fgColor);145 fgColor = WSkinColor::getCorrectColor(fgColor);
@@ -119,26 +148,24 @@
119 pal.setColor(QPalette::AlternateBase, r2);148 pal.setColor(QPalette::AlternateBase, r2);
120 pal.setColor(QPalette::Text, text);149 pal.setColor(QPalette::Text, text);
121 pal.setColor(QPalette::WindowText, fgColor);150 pal.setColor(QPalette::WindowText, fgColor);
122
123 }151 }
124152
125 setPalette(pal);153 setPalette(pal);
126154
127 pushButtonAutoDJ->setPalette(pal);155 pushButtonAutoDJ->setPalette(pal);
128 //m_pTrackTableView->setPalette(pal); //Since we're getting this passed into us already created,156
129 //shouldn't need to set the palette.157 // Since we're getting this passed into us already created, shouldn't need
130}158 // to set the palette.
131159 //m_pTrackTableView->setPalette(pal);
132void DlgAutoDJ::onSearchStarting()160}
133{161
134}162void DlgAutoDJ::onSearchStarting() {
135163}
136void DlgAutoDJ::onSearchCleared()164
137{165void DlgAutoDJ::onSearchCleared() {
138}166}
139167
140void DlgAutoDJ::onSearch(const QString& text)168void DlgAutoDJ::onSearch(const QString& text) {
141{
142 m_pAutoDJTableModel->search(text);169 m_pAutoDJTableModel->search(text);
143}170}
144171
@@ -154,204 +181,439 @@
154 m_pTrackTableView->moveSelection(delta);181 m_pTrackTableView->moveSelection(delta);
155}182}
156183
157void DlgAutoDJ::shufflePlaylist(bool buttonChecked)184void DlgAutoDJ::shufflePlaylist(bool buttonChecked) {
158{
159 Q_UNUSED(buttonChecked);185 Q_UNUSED(buttonChecked);
160 qDebug() << "Shuffling AutoDJ playlist";186 qDebug() << "Shuffling AutoDJ playlist";
161 m_pAutoDJTableModel->shuffleTracks(m_pAutoDJTableModel->index(0, 0));187 m_pAutoDJTableModel->shuffleTracks(m_pAutoDJTableModel->index(0, 0));
162 qDebug() << "Shuffling done";188 qDebug() << "Shuffling done";
163}189}
164190
165void DlgAutoDJ::toggleAutoDJ(bool toggle)191void DlgAutoDJ::skipNext(bool buttonChecked) {
166{192 Q_UNUSED(buttonChecked);
167 if (toggle) //Enable Auto DJ193 qDebug() << "Skip Next";
168 {194 // Load the next song from the queue.
169 if (m_pCOPlay1->get() == 1.0f && m_pCOPlay2->get() == 1.0f) {195 if (m_pCOPlay1Fb->get() == 0.0f) {
196 removePlayingTrackFromQueue("[Channel1]");
197 loadNextTrackFromQueue();
198 } else if (m_pCOPlay2Fb->get() == 0.0f) {
199 removePlayingTrackFromQueue("[Channel2]");
200 loadNextTrackFromQueue();
201 }
202}
203
204void DlgAutoDJ::fadeNow(bool buttonChecked) {
205 Q_UNUSED(buttonChecked);
206 qDebug() << "Fade Now";
207 if (m_eState == ADJ_IDLE && m_bAutoDJEnabled) {
208 m_bFadeNow = true;
209 double crossfader = m_pCOCrossfader->get();
210 if (crossfader <= 0.3f && m_pCOPlay1Fb->get() == 1.0f) {
211 m_posThreshold1 = m_pCOPlayPos1->get() -
212 ((crossfader + 1.0f) / 2 * (m_fadeDuration1));
213 // Repeat is disabled by FadeNow but disables auto Fade
214 m_pCORepeat1->slotSet(0.0f);
215 } else if (crossfader >= -0.3f && m_pCOPlay2Fb->get() == 1.0f) {
216 m_posThreshold2 = m_pCOPlayPos2->get() -
217 ((1.0f - crossfader) / 2 * (m_fadeDuration2));
218 // Repeat is disabled by FadeNow but disables auto Fade
219 m_pCORepeat2->slotSet(0.0f);
220 }
221 }
222}
223
224void DlgAutoDJ::toggleAutoDJ(bool toggle) {
225 bool deck1Playing = m_pCOPlay1Fb->get() == 1.0f;
226 bool deck2Playing = m_pCOPlay2Fb->get() == 1.0f;
227
228 if (toggle) { // Enable Auto DJ
229 if (deck1Playing && deck2Playing) {
230 QMessageBox::warning(
231 NULL, tr("Auto-DJ"),
232 tr("One player must be stopped to enable Auto-DJ mode."),
233 QMessageBox::Ok);
170 qDebug() << "One player must be stopped before enabling Auto DJ mode";234 qDebug() << "One player must be stopped before enabling Auto DJ mode";
171 pushButtonAutoDJ->setChecked(false);235 pushButtonAutoDJ->setChecked(false);
172 return;236 return;
173 }237 }
174238
239 // Never load the same track if it is already playing
240 if (deck1Playing) {
241 removePlayingTrackFromQueue("[Channel1]");
242 }
243 if (deck2Playing) {
244 removePlayingTrackFromQueue("[Channel2]");
245 }
246
247 TrackPointer nextTrack = getNextTrackFromQueue();
248 if (!nextTrack) {
249 qDebug() << "Queue is empty now";
250 pushButtonAutoDJ->setChecked(false);
251 return;
252 }
253
254 // Track is available so GO
255 pushButtonAutoDJ->setToolTip(tr("Disable Auto DJ"));
175 pushButtonAutoDJ->setText(tr("Disable Auto DJ"));256 pushButtonAutoDJ->setText(tr("Disable Auto DJ"));
257 qDebug() << "Auto DJ enabled";
176 m_bAutoDJEnabled = true;258 m_bAutoDJEnabled = true;
259
177 connect(m_pCOPlayPos1, SIGNAL(valueChanged(double)),260 connect(m_pCOPlayPos1, SIGNAL(valueChanged(double)),
178 this, SLOT(player1PositionChanged(double)));261 this, SLOT(player1PositionChanged(double)));
179 connect(m_pCOPlayPos2, SIGNAL(valueChanged(double)),262 connect(m_pCOPlayPos2, SIGNAL(valueChanged(double)),
180 this, SLOT(player2PositionChanged(double)));263 this, SLOT(player2PositionChanged(double)));
181264
182265 connect(m_pCOPlay1Fb, SIGNAL(valueChanged(double)),
183 //Manually override the "next track is already loaded" flag266 this, SLOT(player1PlayChanged(double)));
184 //because we've already primed a player with the first track.267 connect(m_pCOPlay2Fb, SIGNAL(valueChanged(double)),
185 //We do this so that you don't lose the first song in your268 this, SLOT(player2PlayChanged(double)));
186 //Auto DJ queue if you enable Auto DJ then change your mind269
187 //and disable it right away. This just makes it a little bit270 if (!deck1Playing && !deck2Playing) {
188 //more user friendly. :)271 // both decks are stopped
189 //m_bNextTrackAlreadyLoaded = true;272 m_eState = ADJ_ENABLE_P1LOADED;
190 m_bPlayer1Primed = false;273 // Force Update on load Track
191 m_bPlayer2Primed = false;274 m_pCOPlayPos1->slotSet(-0.001f);
192275 } else if (deck1Playing) {
193 //If there are no tracks in the Auto DJ queue, disable Auto DJ mode.276 // deck 1 is already playing
194 /* if (m_pAutoDJTableModel->rowCount() == 0)277 m_eState = ADJ_IDLE;
195 {278 player1PlayChanged(1.0f);
196 //Queue was empty. Disable and return.279 } else {
197 pushButtonAutoDJ->setChecked(false);280 // deck 2 is already playing
198 return;281 m_eState = ADJ_IDLE;
199 }*/ //don't need this code, above block takes care of this case.282 player2PlayChanged(1.0f);
200283 }
201 //If only one of the players is playing...284 // Loads into first deck If stopped else into second else not
202 if ((m_pCOPlay1->get() == 1.0f && m_pCOPlay2->get() == 0.0f) ||285 emit(loadTrack(nextTrack));
203 (m_pCOPlay1->get() == 0.0f && m_pCOPlay2->get() == 1.0f))286 } else { // Disable Auto DJ
204 {287 pushButtonAutoDJ->setToolTip(tr("Enable Auto DJ"));
205 //Load the first song from the queue.
206 if (!loadNextTrackFromQueue(false)) {
207 //Queue was empty. Disable and return.
208 pushButtonAutoDJ->setChecked(false);
209 return;
210 }
211 //Set the primed flags so the crossfading algorithm knows
212 //that it doesn't need to load a track into whatever player.
213 if (m_pCOPlay1->get() == 1.0f)
214 {
215 m_bPlayer1Primed = true;
216 }
217 if (m_pCOPlay2->get() == 1.0f)
218 {
219 m_bPlayer2Primed = true;
220 }
221 }
222 //If both players are stopped, start the first one (which should have just had a track loaded into it)
223 else if (m_pCOPlay1->get() == 0.0f && m_pCOPlay2->get() == 0.0f) {
224 //Load the first song from the queue.
225 if (!loadNextTrackFromQueue(false)) {
226 //Queue was empty. Disable and return.
227 pushButtonAutoDJ->setChecked(false);
228 return;
229 }
230 m_pCOCrossfader->slotSet(-1.0f); //Move crossfader to the left!
231 m_pCORepeat1->slotSet(1.0f); //Turn on repeat mode to avoid race condition between async load
232 //and "play" command.
233 m_pCOPlay1->slotSet(1.0f); //Play the track in player 1
234 }
235 }
236 else //Disable Auto DJ
237 {
238 pushButtonAutoDJ->setText(tr("Enable Auto DJ"));288 pushButtonAutoDJ->setText(tr("Enable Auto DJ"));
239 qDebug() << "Auto DJ disabled";289 qDebug() << "Auto DJ disabled";
240 m_bAutoDJEnabled = false;290 m_bAutoDJEnabled = false;
291 m_bFadeNow = false;
241 m_pCOPlayPos1->disconnect(this);292 m_pCOPlayPos1->disconnect(this);
242 m_pCOPlayPos2->disconnect(this);293 m_pCOPlayPos2->disconnect(this);
243 m_pCORepeat1->slotSet(0.0f); //Turn off repeat mode294 m_pCOPlay1->disconnect(this);
244 m_pCORepeat2->slotSet(0.0f); //Turn off repeat mode295 m_pCOPlay2->disconnect(this);
245 }296 }
246}297}
247298
248void DlgAutoDJ::player1PositionChanged(double value)299void DlgAutoDJ::player1PositionChanged(double value) {
249{300 // 95% playback is when we crossfade and do stuff
250 const float posThreshold = 0.95; //95% playback is when we crossfade and do stuff301 // const float posThreshold = 0.95;
251 if (value > posThreshold)302
252 {303 // 0.05; // 5% playback is crossfade duration
253 //Crossfade!304 const float fadeDuration = m_fadeDuration1;
254 float crossfadeValue = -1.0f + 2*(value-posThreshold)/(1.0f-posThreshold);305
255 m_pCOCrossfader->slotSet(crossfadeValue); //Move crossfader to the right!306 // qDebug() << "player1PositionChanged(" << value << ")";
256 //If the second player doesn't have a new track loaded in it...307 if (!m_bAutoDJEnabled) {
257 if (!m_bPlayer2Primed)308 //nothing to do
258 {309 return;
259 qDebug() << "pp1c loading";310 }
260311
261 //Load the next track into Player 2312 bool deck1Playing = m_pCOPlay1Fb->get() == 1.0f;
262 //if (!m_bNextTrackAlreadyLoaded) //Fudge to make us not skip the first track313 bool deck2Playing = m_pCOPlay2Fb->get() == 1.0f;
263 {314
264 if (!loadNextTrackFromQueue(true))315 if (m_eState == ADJ_ENABLE_P1LOADED) {
265 return;316 // Auto DJ Start
266 }317 if (!deck1Playing && !deck2Playing) {
267 //m_bNextTrackAlreadyLoaded = false; //Reset fudge318 m_pCOCrossfader->slotSet(-1.0f); // Move crossfader to the left!
268 m_bPlayer2Primed = true;319 m_pCOPlay1->slotSet(1.0f); // Play the track in player 1
269 }320 removePlayingTrackFromQueue("[Channel1]");
270 //If the second player is stopped...321 } else if (deck1Playing && !deck2Playing) {
271 if (m_pCOPlay2->get() == 0.0f)322 // Here we are, if first deck was playing before starting Auto DJ
272 {323 // or if it was started just before
273 //Turn off repeat mode to tell Player 1 to stop at the end324 loadNextTrackFromQueue();
274 m_pCORepeat1->slotSet(0.0f);325 m_eState = ADJ_IDLE;
275326 // if we start the deck from code we don`t get a signal
276 //Turn on repeat mode to tell Player 2 to start playing when the new track is loaded.327 player1PlayChanged(1.0f);
277 //This helps us get around the fact that it takes time for the track to be loaded328 // call function manually
278 //and that is executed asynchronously (so we get around the race condition).329 } else {
279 m_pCORepeat2->slotSet(1.0f);330 m_eState = ADJ_IDLE;
280 //Play!331 player2PlayChanged(1.0f);
281 m_pCOPlay2->slotSet(1.0f);332 }
282 }333 return;
283334 }
284 if (value == 1.0f)335
285 {336 if (m_eState == ADJ_P2FADING) {
286 m_pCOPlay1->slotSet(0.0f); //Stop the player337 if (deck1Playing && !deck2Playing) {
287 m_bPlayer1Primed = false;338 loadNextTrackFromQueue();
288 }339 // End State
289 }340 m_pCOCrossfader->slotSet(-1.0f); // Move crossfader to the left!
290}341 // qDebug() << "1: m_pCOCrossfader->slotSet(_-1.0f_);";
291342 m_eState = ADJ_IDLE;
292void DlgAutoDJ::player2PositionChanged(double value)343 }
293{344 return;
294 const float posThreshold = 0.95; //95% playback is when we crossfade and do stuff345 }
295 if (value > posThreshold)346
296 {347 if (m_eState == ADJ_IDLE) {
297 //Crossfade!348 if (m_pCORepeat1->get() == 1.0f) {
298 float crossfadeValue = 1.0f - 2*(value-posThreshold)/(1.0f-posThreshold);349 // repeat disables auto DJ
299 m_pCOCrossfader->slotSet(crossfadeValue); //Move crossfader to the right!350 return;
300351 }
301 //If the first player doesn't have the next track loaded, load a track into352 }
302 //it and start playing it!353
303 if (!m_bPlayer1Primed)354 if (value >= m_posThreshold1) {
304 {355 if (m_eState == ADJ_IDLE &&
305 //Load the next track into player 1356 (deck1Playing || m_posThreshold1 >= 1.0f)) {
306 //if (!m_bNextTrackAlreadyLoaded) //Fudge to make us not skip the first track357 if (!deck2Playing) {
307 {358 // Start Deck 2
308 if (!loadNextTrackFromQueue(true))359 player2PlayChanged(1.0f);
309 return;360 m_pCOPlay2->slotSet(1.0f);
310 }361 if (fadeDuration < 0.0f) {
311 //m_bNextTrackAlreadyLoaded = false; //Reset fudge362 // Scroll back for pause between tracks
312 m_bPlayer1Primed = true;363 m_pCOPlayPos2->slotSet(m_fadeDuration2);
313 }364 }
314 if (m_pCOPlay1->get() == 0.0f)365 }
315 {366 removePlayingTrackFromQueue("[Channel2]");
316 //Turn off repeat mode to tell Player 2 to stop at the end367 m_eState = ADJ_P1FADING;
317 m_pCORepeat2->slotSet(0.0f);368 }
318369
319 //Turn on repeat mode to tell Player 1 to start playing when the new track is loaded.370 float posFadeEnd = math_min(1.0, m_posThreshold1 + fadeDuration);
320 //This helps us get around the fact that it takes time for the track to be loaded371
321 //and that is executed asynchronously (so we get around the race condition).372 if (value >= posFadeEnd) {
322 m_pCORepeat1->slotSet(1.0f);373 // Pre-EndState
323 m_pCOPlay1->slotSet(1.0f);374 // m_pCOCrossfader->slotSet(1.0f); //Move crossfader to the right!
324 }375
325376 m_pCOPlay1->slotSet(0.0f); // Stop the player
326 if (value == 1.0f)377 //m_posThreshold = 1.0f - fadeDuration; // back to default
327 {378
328 m_pCOPlay2->slotSet(0.0f); //Stop the player379 // does not work always immediately after stop
329 m_bPlayer2Primed = false;380 // loadNextTrackFromQueue();
330 }381 // m_eState = ADJ_IDLE; // Fading ready
331 }382 } else {
332}383 // Crossfade!
333384 float crossfadeValue = -1.0f +
334385 2*(value-m_posThreshold1)/(posFadeEnd-m_posThreshold1);
335bool DlgAutoDJ::loadNextTrackFromQueue(bool removeTopMostBeforeLoading)386 // crossfadeValue = -1.0f -> + 1.0f
336{387 // Move crossfader to the right!
337 if (removeTopMostBeforeLoading) {388 m_pCOCrossfader->slotSet(crossfadeValue);
338 //Only remove the top track if this isn't the start of Auto DJ mode.389 // qDebug() << "1: m_pCOCrossfader->slotSet " << crossfadeValue;
339 m_pAutoDJTableModel->removeTrack(m_pAutoDJTableModel->index(0, 0));390 }
340 }391 }
341392}
342 //Get the track at the top of the playlist...393
343 TrackPointer nextTrack = m_pAutoDJTableModel->getTrack(m_pAutoDJTableModel->index(0, 0));394void DlgAutoDJ::player2PositionChanged(double value) {
344395 // 95% playback is when we crossfade and do stuff
345 if (!nextTrack) //We ran out of tracks in the queue...396 // const float posThreshold = 0.95;
346 {397
347 //Disable auto DJ and return...398 // 0.05; // 5% playback is crossfade duration
399 float fadeDuration = m_fadeDuration2;
400
401 //qDebug() << "player2PositionChanged(" << value << ")";
402 if (!m_bAutoDJEnabled) {
403 //nothing to do
404 return;
405 }
406
407 bool deck1Playing = m_pCOPlay1Fb->get() == 1.0f;
408 bool deck2Playing = m_pCOPlay2Fb->get() == 1.0f;
409
410 if (m_eState == ADJ_P1FADING) {
411 if (!deck1Playing && deck2Playing) {
412 // End State
413 // Move crossfader to the right!
414 m_pCOCrossfader->slotSet(1.0f);
415 // qDebug() << "1: m_pCOCrossfader->slotSet(_1.0f_);";
416 m_eState = ADJ_IDLE;
417 loadNextTrackFromQueue();
418 }
419 return;
420 }
421
422 if (m_eState == ADJ_IDLE) {
423 if (m_pCORepeat2->get() == 1.0f) {
424 //repeat disables auto DJ
425 return;
426 }
427 }
428
429 if (value >= m_posThreshold2) {
430 if (m_eState == ADJ_IDLE &&
431 (deck2Playing || m_posThreshold2 >= 1.0f)) {
432 if (!deck1Playing) {
433 player1PlayChanged(1.0f);
434 m_pCOPlay1->slotSet(1.0f);
435 if (fadeDuration < 0) {
436 // Scroll back for pause between tracks
437 m_pCOPlayPos1->slotSet(m_fadeDuration1);
438 }
439 }
440 removePlayingTrackFromQueue("[Channel1]");
441 m_eState = ADJ_P2FADING;
442 }
443
444 float posFadeEnd = math_min(1.0, m_posThreshold2 + fadeDuration);
445
446 if (value >= posFadeEnd) {
447 // Pre-End State
448 //m_pCOCrossfader->slotSet(-1.0f); //Move crossfader to the left!
449
450 m_pCOPlay2->slotSet(0.0f); // Stop the player
451
452 //m_posThreshold = 1.0f - fadeDuration; // back to default
453
454 // does not work always immediately after stop
455 // loadNextTrackFromQueue();
456 // m_eState = ADJ_IDLE; // Fading ready
457 } else {
458 //Crossfade!
459 float crossfadeValue = 1.0f -
460 2*(value-m_posThreshold2)/(posFadeEnd-m_posThreshold2);
461 // crossfadeValue = 1.0f -> + -1.0f
462 m_pCOCrossfader->slotSet(crossfadeValue); //Move crossfader to the right!
463 // qDebug() << "2: m_pCOCrossfader->slotSet " << crossfadeValue;
464 }
465 }
466}
467
468TrackPointer DlgAutoDJ::getNextTrackFromQueue() {
469 // Get the track at the top of the playlist...
470 TrackPointer nextTrack;
471
472 while (true) {
473 nextTrack = m_pAutoDJTableModel->getTrack(
474 m_pAutoDJTableModel->index(0, 0));
475
476 if (nextTrack) {
477 if (nextTrack->exists()) {
478 // found a valid Track
479 return nextTrack;
480 } else {
481 // Remove missing song from auto DJ playlist
482 m_pAutoDJTableModel->removeTrack(
483 m_pAutoDJTableModel->index(0, 0));
484 }
485 } else {
486 // we are running out of tracks
487 break;
488 }
489 }
490 return nextTrack;
491}
492
493bool DlgAutoDJ::loadNextTrackFromQueue() {
494 TrackPointer nextTrack = getNextTrackFromQueue();
495
496 // We ran out of tracks in the queue...
497 if (!nextTrack) {
498 // Disable auto DJ and return...
348 pushButtonAutoDJ->setChecked(false);499 pushButtonAutoDJ->setChecked(false);
349 return false;500 return false;
350 }501 }
351502
352 //m_bNextTrackAlreadyLoaded = false;
353
354 emit(loadTrack(nextTrack));503 emit(loadTrack(nextTrack));
355504 return true;
356 return true;505}
506
507bool DlgAutoDJ::removePlayingTrackFromQueue(QString group) {
508 TrackPointer nextTrack, loadedTrack;
509 int nextId = 0, loadedId = 0;
510
511 // Get the track at the top of the playlist...
512 nextTrack = m_pAutoDJTableModel->getTrack(m_pAutoDJTableModel->index(0, 0));
513 if (nextTrack) {
514 nextId = nextTrack->getId();
515 }
516
517 // Get loaded track
518 loadedTrack = PlayerInfo::Instance().getTrackInfo(group);
519 if (loadedTrack) {
520 loadedId = loadedTrack->getId();
521 }
522
523 // When enable auto DJ and Topmost Song is already on second deck, nothing to do
524 // BaseTrackPlayer::getLoadedTrack()
525 // pTrack = PlayerInfo::Instance().getCurrentPlayingTrack();
526
527 if (loadedId != nextId) {
528 // Do not remove when the user has loaded a track manualy
529 return false;
530 }
531
532 // remove the top track
533 m_pAutoDJTableModel->removeTrack(m_pAutoDJTableModel->index(0, 0));
534
535 return true;
536}
537
538void DlgAutoDJ::player1PlayChanged(double value) {
539 //qDebug() << "player1PlayChanged(" << value << ")";
540 if (!m_bAutoDJEnabled) {
541 return;
542 }
543
544 if (value == 1.0f && m_eState == ADJ_IDLE) {
545 TrackPointer loadedTrack =
546 PlayerInfo::Instance().getTrackInfo("[Channel1]");
547 if (loadedTrack) {
548 int TrackDuration = loadedTrack->getDuration();
549 qDebug() << "TrackDuration = " << TrackDuration;
550
551 int autoDjTransition = spinBoxTransition->value();
552
553 if (TrackDuration > autoDjTransition) {
554 m_fadeDuration1 = static_cast<float>(autoDjTransition) /
555 static_cast<float>(TrackDuration);
556 } else {
557 m_fadeDuration1 = 0;
558 }
559
560 if (autoDjTransition > 0) {
561 m_posThreshold1 = 1.0f - m_fadeDuration1;
562 } else {
563 // in case of pause
564 m_posThreshold1 = 1.0f;
565 }
566 qDebug() << "m_fadeDuration1 = " << m_fadeDuration1;
567 }
568 }
569}
570
571void DlgAutoDJ::player2PlayChanged(double value) {
572 //qDebug() << "player2PlayChanged(" << value << ")";
573 if (!m_bAutoDJEnabled) {
574 return;
575 }
576
577 if (value == 1.0f && m_eState == ADJ_IDLE) {
578 TrackPointer loadedTrack =
579 PlayerInfo::Instance().getTrackInfo("[Channel2]");
580 if (loadedTrack) {
581 int TrackDuration = loadedTrack->getDuration();
582 qDebug() << "TrackDuration = " << TrackDuration;
583
584 int autoDjTransition = spinBoxTransition->value();
585
586 if (TrackDuration > autoDjTransition) {
587 m_fadeDuration2 = static_cast<float>(autoDjTransition) /
588 static_cast<float>(TrackDuration);
589 } else {
590 m_fadeDuration2 = 0;
591 }
592
593 if (autoDjTransition > 0) {
594 m_posThreshold2 = 1.0f - m_fadeDuration2;
595 } else {
596 // in case of pause
597 m_posThreshold2 = 1.0f;
598 }
599 qDebug() << "m_fadeDuration2 = " << m_fadeDuration2;
600 }
601 }
602}
603
604void DlgAutoDJ::transitionValueChanged(int value) {
605 if (m_bAutoDJEnabled && m_eState == ADJ_IDLE) {
606 if (m_pCOPlay1Fb->get() == 1.0f) {
607 player1PlayChanged(1.0f);
608 }
609 if (m_pCOPlay2Fb->get() == 1.0f) {
610 player2PlayChanged(1.0f);
611 }
612 }
613 m_pConfig->set(ConfigKey(CONFIG_KEY, kTransitionPreferenceName),
614 ConfigValue(value));
615}
616
617bool DlgAutoDJ::appendTrack(int trackId) {
618 return m_pAutoDJTableModel->appendTrack(trackId);
357}619}
358620
=== modified file 'mixxx/src/dlgautodj.h'
--- mixxx/src/dlgautodj.h 2011-04-24 06:00:11 +0000
+++ mixxx/src/dlgautodj.h 2012-03-12 04:06:20 +0000
@@ -31,19 +31,35 @@
31 virtual void loadSelectedTrack();31 virtual void loadSelectedTrack();
32 virtual void loadSelectedTrackToGroup(QString group);32 virtual void loadSelectedTrackToGroup(QString group);
33 virtual void moveSelection(int delta);33 virtual void moveSelection(int delta);
34 virtual bool appendTrack(int trackId);
3435
35 public slots:36 public slots:
36 void shufflePlaylist(bool buttonChecked);37 void shufflePlaylist(bool buttonChecked);
38 void skipNext(bool buttonChecked);
39 void fadeNow(bool buttonChecked);
37 void toggleAutoDJ(bool toggle);40 void toggleAutoDJ(bool toggle);
38 void player1PositionChanged(double value);41 void player1PositionChanged(double value);
39 void player2PositionChanged(double value);42 void player2PositionChanged(double value);
43 void player1PlayChanged(double value);
44 void player2PlayChanged(double value);
45 void transitionValueChanged(int value);
4046
41 signals:47 signals:
42 void loadTrack(TrackPointer tio);48 void loadTrack(TrackPointer tio);
43 void loadTrackToPlayer(TrackPointer tio, QString group);49 void loadTrackToPlayer(TrackPointer tio, QString group);
4450
45 private:51 private:
46 bool loadNextTrackFromQueue(bool removeTopMostBeforeLoading);52 enum ADJstates {
53 ADJ_IDLE = 0,
54 ADJ_P1FADING,
55 ADJ_P2FADING,
56 ADJ_ENABLE_P1LOADED,
57 ADJ_ENABLE_P1PLAYING
58 };
59
60 TrackPointer getNextTrackFromQueue();
61 bool loadNextTrackFromQueue();
62 bool removePlayingTrackFromQueue(QString group);
4763
48 ConfigObject<ConfigValue>* m_pConfig;64 ConfigObject<ConfigValue>* m_pConfig;
49 TrackCollection* m_pTrackCollection;65 TrackCollection* m_pTrackCollection;
@@ -51,17 +67,24 @@
51 PlaylistTableModel* m_pAutoDJTableModel;67 PlaylistTableModel* m_pAutoDJTableModel;
52 PlaylistDAO& m_playlistDao;68 PlaylistDAO& m_playlistDao;
53 bool m_bAutoDJEnabled;69 bool m_bAutoDJEnabled;
54 bool m_bNextTrackAlreadyLoaded; /** Makes our Auto DJ logic assume the70
55 next track that should be played is71 // Makes our Auto DJ logic assume the next track that should be played is
56 already loaded. We need this flag to72 // already loaded. We need this flag to make our
57 make our first-track-gets-loaded-but-73 // first-track-gets-loaded-but- not-removed-from-the-queue behaviour work.
58 not-removed-from-the-queue behaviour74 bool m_bNextTrackAlreadyLoaded;
59 work. */75
60 bool m_bPlayer1Primed, m_bPlayer2Primed;76 bool m_bFadeNow;
77 enum ADJstates m_eState;
78 float m_posThreshold1;
79 float m_posThreshold2;
80 float m_fadeDuration1;
81 float m_fadeDuration2;
61 ControlObjectThreadMain* m_pCOPlayPos1;82 ControlObjectThreadMain* m_pCOPlayPos1;
62 ControlObjectThreadMain* m_pCOPlayPos2;83 ControlObjectThreadMain* m_pCOPlayPos2;
63 ControlObjectThreadMain* m_pCOPlay1;84 ControlObjectThreadMain* m_pCOPlay1;
64 ControlObjectThreadMain* m_pCOPlay2;85 ControlObjectThreadMain* m_pCOPlay2;
86 ControlObjectThreadMain* m_pCOPlay1Fb;
87 ControlObjectThreadMain* m_pCOPlay2Fb;
65 ControlObjectThreadMain* m_pCORepeat1;88 ControlObjectThreadMain* m_pCORepeat1;
66 ControlObjectThreadMain* m_pCORepeat2;89 ControlObjectThreadMain* m_pCORepeat2;
67 ControlObjectThreadMain* m_pCOCrossfader;90 ControlObjectThreadMain* m_pCOCrossfader;
@@ -82,7 +105,7 @@
82105
83106
84#define _blah if ((QDate::currentDate().day() == 1) && (QDate::currentDate().month() == 4)) \107#define _blah if ((QDate::currentDate().day() == 1) && (QDate::currentDate().month() == 4)) \
85 pushButtonAutoDJ->setText("\x45\x6e\x61\x62\x6c\x65\x20\x50\x65\x65" \108 pushButtonAutoDJ->setText("\x45\x6e\x61\x62\x6c\x65\x20\x50\x65\x65" \
86 "\x20\x42\x72\x65\x61\x6b\x20\x4d\x6f\x64\x65")109 "\x20\x42\x72\x65\x61\x6b\x20\x4d\x6f\x64\x65")
87110
88111
89112
=== modified file 'mixxx/src/dlgautodj.ui'
--- mixxx/src/dlgautodj.ui 2011-10-05 03:30:02 +0000
+++ mixxx/src/dlgautodj.ui 2012-03-12 04:06:20 +0000
@@ -6,13 +6,28 @@
6 <rect>6 <rect>
7 <x>0</x>7 <x>0</x>
8 <y>0</y>8 <y>0</y>
9 <width>582</width>9 <width>500</width>
10 <height>399</height>10 <height>399</height>
11 </rect>11 </rect>
12 </property>12 </property>
13 <property name="windowTitle">13 <property name="windowTitle">
14 <string>Manage</string>14 <string>Manage</string>
15 </property>15 </property>
16 <property name="styleSheet">
17 <string notr="true">#pushButtonShuffle{
18 border-image: url(:/images/autodj/media-playlist-shuffle.svg);
19}
20
21#pushButtonSkipNext{
22 border-image: url(:/images/autodj/bottom.svg);
23}
24
25#pushButtonFadeNow{
26 border-image: url(:/images/autodj/stock_mail-send-receive.svg);
27}
28
29</string>
30 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">31 <layout class="QVBoxLayout" name="verticalLayout">
17 <property name="leftMargin">32 <property name="leftMargin">
18 <number>0</number>33 <number>0</number>
@@ -25,13 +40,89 @@
25 </property>40 </property>
26 <item>41 <item>
27 <layout class="QHBoxLayout" name="horizontalLayout">42 <layout class="QHBoxLayout" name="horizontalLayout">
43 <property name="sizeConstraint">
44 <enum>QLayout::SetMinimumSize</enum>
45 </property>
28 <item>46 <item>
29 <widget class="QPushButton" name="pushButtonShuffle">47 <widget class="QPushButton" name="pushButtonShuffle">
30 <property name="text">48 <property name="maximumSize">
31 <string>Shuffle playlist</string>49 <size>
32 </property>50 <width>24</width>
33 <property name="checkable">51 <height>24</height>
34 <bool>false</bool>52 </size>
53 </property>
54 <property name="toolTip">
55 <string>Shuffle Playlist</string>
56 </property>
57 <property name="text">
58 <string/>
59 </property>
60 <property name="checkable">
61 <bool>false</bool>
62 </property>
63 </widget>
64 </item>
65 <item>
66 <widget class="QPushButton" name="pushButtonSkipNext">
67 <property name="maximumSize">
68 <size>
69 <width>24</width>
70 <height>24</height>
71 </size>
72 </property>
73 <property name="toolTip">
74 <string>Skip Next Track</string>
75 </property>
76 <property name="text">
77 <string/>
78 </property>
79 <property name="checkable">
80 <bool>false</bool>
81 </property>
82 </widget>
83 </item>
84 <item>
85 <widget class="QLabel" name="label_2">
86 <property name="text">
87 <string>Transition [sec]</string>
88 </property>
89 </widget>
90 </item>
91 <item>
92 <widget class="QSpinBox" name="spinBoxTransition">
93 <property name="sizePolicy">
94 <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
95 <horstretch>0</horstretch>
96 <verstretch>0</verstretch>
97 </sizepolicy>
98 </property>
99 <property name="maximumSize">
100 <size>
101 <width>45</width>
102 <height>16777215</height>
103 </size>
104 </property>
105 <property name="alignment">
106 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
107 </property>
108 <property name="minimum">
109 <number>-9</number>
110 </property>
111 </widget>
112 </item>
113 <item>
114 <widget class="QPushButton" name="pushButtonFadeNow">
115 <property name="maximumSize">
116 <size>
117 <width>24</width>
118 <height>24</height>
119 </size>
120 </property>
121 <property name="toolTip">
122 <string>Fade Now</string>
123 </property>
124 <property name="text">
125 <string/>
35 </property>126 </property>
36 </widget>127 </widget>
37 </item>128 </item>
@@ -42,24 +133,17 @@
42 </property>133 </property>
43 <property name="sizeHint" stdset="0">134 <property name="sizeHint" stdset="0">
44 <size>135 <size>
45 <width>40</width>136 <width>1</width>
46 <height>20</height>137 <height>20</height>
47 </size>138 </size>
48 </property>139 </property>
49 </spacer>140 </spacer>
50 </item>141 </item>
51 <item>142 <item>
52 <widget class="QLabel" name="label">
53 <property name="text">
54 <string>Add tracks to the queue below...</string>
55 </property>
56 <property name="buddy" >
57 <cstring>m_pTrackTablePlaceholder</cstring>
58 </property>
59 </widget>
60 </item>
61 <item>
62 <widget class="QPushButton" name="pushButtonAutoDJ">143 <widget class="QPushButton" name="pushButtonAutoDJ">
144 <property name="toolTip">
145 <string>Enable Auto DJ</string>
146 </property>
63 <property name="text">147 <property name="text">
64 <string>Enable Auto DJ</string>148 <string>Enable Auto DJ</string>
65 </property>149 </property>
@@ -88,6 +172,12 @@
88 </item>172 </item>
89 <item>173 <item>
90 <widget class="QTableView" name="m_pTrackTablePlaceholder">174 <widget class="QTableView" name="m_pTrackTablePlaceholder">
175 <property name="sizePolicy">
176 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
177 <horstretch>0</horstretch>
178 <verstretch>0</verstretch>
179 </sizepolicy>
180 </property>
91 <property name="showGrid">181 <property name="showGrid">
92 <bool>true</bool>182 <bool>true</bool>
93 </property>183 </property>
@@ -95,6 +185,8 @@
95 </item>185 </item>
96 </layout>186 </layout>
97 </widget>187 </widget>
98 <resources/>188 <resources>
189 <include location="../res/mixxx.qrc"/>
190 </resources>
99 <connections/>191 <connections/>
100</ui>192</ui>
101193
=== modified file 'mixxx/src/library/autodjfeature.cpp'
--- mixxx/src/library/autodjfeature.cpp 2011-10-12 17:29:43 +0000
+++ mixxx/src/library/autodjfeature.cpp 2012-03-12 04:06:20 +0000
@@ -23,6 +23,7 @@
23 m_pConfig(pConfig),23 m_pConfig(pConfig),
24 m_pTrackCollection(pTrackCollection),24 m_pTrackCollection(pTrackCollection),
25 m_playlistDao(pTrackCollection->getPlaylistDAO()) {25 m_playlistDao(pTrackCollection->getPlaylistDAO()) {
26 m_pAutoDJView = NULL;
26}27}
2728
28AutoDJFeature::~AutoDJFeature() {29AutoDJFeature::~AutoDJFeature() {
@@ -36,47 +37,43 @@
36 return QIcon(":/images/library/ic_library_autodj.png");37 return QIcon(":/images/library/ic_library_autodj.png");
37}38}
3839
39void AutoDJFeature::bindWidget(WLibrarySidebar* sidebarWidget,40void AutoDJFeature::bindWidget(WLibrarySidebar* /*sidebarWidget*/,
40 WLibrary* libraryWidget,41 WLibrary* libraryWidget,
41 MixxxKeyboard* keyboard) {42 MixxxKeyboard* keyboard) {
4243 m_pAutoDJView = new DlgAutoDJ(libraryWidget,
43 DlgAutoDJ* pAutoDJView = new DlgAutoDJ(libraryWidget,44 m_pConfig,
44 m_pConfig,45 m_pTrackCollection,
45 m_pTrackCollection,46 keyboard);
46 keyboard);47 m_pAutoDJView->installEventFilter(keyboard);
47 pAutoDJView->installEventFilter(keyboard);48 libraryWidget->registerView(m_sAutoDJViewName, m_pAutoDJView);
48 libraryWidget->registerView(m_sAutoDJViewName, pAutoDJView);49 connect(m_pAutoDJView, SIGNAL(loadTrack(TrackPointer)),
49 connect(pAutoDJView, SIGNAL(loadTrack(TrackPointer)),
50 this, SIGNAL(loadTrack(TrackPointer)));50 this, SIGNAL(loadTrack(TrackPointer)));
51 connect(pAutoDJView, SIGNAL(loadTrackToPlayer(TrackPointer, QString)),51 connect(m_pAutoDJView, SIGNAL(loadTrackToPlayer(TrackPointer, QString)),
52 this, SIGNAL(loadTrackToPlayer(TrackPointer, QString)));52 this, SIGNAL(loadTrackToPlayer(TrackPointer, QString)));
53}53}
5454
55TreeItemModel* AutoDJFeature::getChildModel() {55TreeItemModel* AutoDJFeature::getChildModel() {
56 return &m_childModel;56 return &m_childModel;
57}57}
5858
59void AutoDJFeature::activate() {59void AutoDJFeature::activate() {
60 //qDebug() << "AutoDJFeature::activate()";60 //qDebug() << "AutoDJFeature::activate()";
61 //emit(showTrackModel(m_pAutoDJTableModelProxy));61 //emit(showTrackModel(m_pAutoDJTableModelProxy));
62 emit(switchToView("Auto DJ"));62 emit(switchToView(m_sAutoDJViewName));
63}63}
6464
65void AutoDJFeature::activateChild(const QModelIndex& index) {65void AutoDJFeature::activateChild(const QModelIndex& /*index*/) {
6666}
67}67
6868void AutoDJFeature::onRightClick(const QPoint& /*globalPos*/) {
69void AutoDJFeature::onRightClick(const QPoint& globalPos) {69}
70}70
7171void AutoDJFeature::onRightClickChild(const QPoint& /*globalPos*/,
72void AutoDJFeature::onRightClickChild(const QPoint& globalPos,72 QModelIndex /*index*/) {
73 QModelIndex index) {
74}73}
7574
76bool AutoDJFeature::dropAccept(QUrl url) {75bool AutoDJFeature::dropAccept(QUrl url) {
77
78 //TODO: Filter by supported formats regex and reject anything that doesn't match.76 //TODO: Filter by supported formats regex and reject anything that doesn't match.
79
80 TrackDAO &trackDao = m_pTrackCollection->getTrackDAO();77 TrackDAO &trackDao = m_pTrackCollection->getTrackDAO();
8178
82 //If a track is dropped onto a playlist's name, but the track isn't in the library,79 //If a track is dropped onto a playlist's name, but the track isn't in the library,
@@ -98,12 +95,17 @@
98 }95 }
9996
100 // TODO(XXX) No feedback on whether this worked.97 // TODO(XXX) No feedback on whether this worked.
101 int playlistId = m_playlistDao.getPlaylistIdFromName(AUTODJ_TABLE);98 if (m_pAutoDJView) {
102 m_playlistDao.appendTrackToPlaylist(trackId, playlistId);99 m_pAutoDJView->appendTrack(trackId);
100 } else {
101 int playlistId = m_playlistDao.getPlaylistIdFromName(AUTODJ_TABLE);
102 m_playlistDao.appendTrackToPlaylist(trackId, playlistId);
103 }
104
103 return true;105 return true;
104}106}
105107
106bool AutoDJFeature::dropAcceptChild(const QModelIndex& index, QUrl url) {108bool AutoDJFeature::dropAcceptChild(const QModelIndex& /*index*/, QUrl /*url*/) {
107 return false;109 return false;
108}110}
109111
@@ -112,10 +114,10 @@
112 return SoundSourceProxy::isFilenameSupported(file.fileName());114 return SoundSourceProxy::isFilenameSupported(file.fileName());
113}115}
114116
115bool AutoDJFeature::dragMoveAcceptChild(const QModelIndex& index,117bool AutoDJFeature::dragMoveAcceptChild(const QModelIndex& /*index*/,
116 QUrl url) {118 QUrl /*url*/) {
117 return false;119 return false;
118}120}
119void AutoDJFeature::onLazyChildExpandation(const QModelIndex &index){121void AutoDJFeature::onLazyChildExpandation(const QModelIndex& /*index*/){
120 //Nothing to do because the childmodel is not of lazy nature.122 //Nothing to do because the childmodel is not of lazy nature.
121}123}
122124
=== modified file 'mixxx/src/library/autodjfeature.h'
--- mixxx/src/library/autodjfeature.h 2011-03-10 13:37:21 +0000
+++ mixxx/src/library/autodjfeature.h 2012-03-12 04:06:20 +0000
@@ -11,13 +11,14 @@
11#include "library/dao/playlistdao.h"11#include "library/dao/playlistdao.h"
12#include "configobject.h"12#include "configobject.h"
13#include "treeitemmodel.h"13#include "treeitemmodel.h"
14#include "dlgautodj.h"
1415
15class PlaylistTableModel;16class PlaylistTableModel;
16class TrackCollection;17class TrackCollection;
1718
18class AutoDJFeature : public LibraryFeature {19class AutoDJFeature : public LibraryFeature {
19 Q_OBJECT20 Q_OBJECT
20 public:21 public:
21 AutoDJFeature(QObject* parent,22 AutoDJFeature(QObject* parent,
22 ConfigObject<ConfigValue>* pConfig,23 ConfigObject<ConfigValue>* pConfig,
23 TrackCollection* pTrackCollection);24 TrackCollection* pTrackCollection);
@@ -37,19 +38,20 @@
3738
38 TreeItemModel* getChildModel();39 TreeItemModel* getChildModel();
3940
40public slots:41 public slots:
41 void activate();42 void activate();
42 void activateChild(const QModelIndex& index);43 void activateChild(const QModelIndex& index);
43 void onRightClick(const QPoint& globalPos);44 void onRightClick(const QPoint& globalPos);
44 void onRightClickChild(const QPoint& globalPos, QModelIndex index);45 void onRightClickChild(const QPoint& globalPos, QModelIndex index);
45 void onLazyChildExpandation(const QModelIndex& index);46 void onLazyChildExpandation(const QModelIndex& index);
4647
47private:48 private:
48 ConfigObject<ConfigValue>* m_pConfig;49 ConfigObject<ConfigValue>* m_pConfig;
49 TrackCollection* m_pTrackCollection;50 TrackCollection* m_pTrackCollection;
50 PlaylistDAO& m_playlistDao;51 PlaylistDAO& m_playlistDao;
51 const static QString m_sAutoDJViewName;52 const static QString m_sAutoDJViewName;
52 TreeItemModel m_childModel;53 TreeItemModel m_childModel;
54 DlgAutoDJ* m_pAutoDJView;
53};55};
5456
5557
5658
=== modified file 'mixxx/src/library/browse/browsefeature.cpp'
--- mixxx/src/library/browse/browsefeature.cpp 2012-01-07 08:36:51 +0000
+++ mixxx/src/library/browse/browsefeature.cpp 2012-03-12 04:06:20 +0000
@@ -14,7 +14,8 @@
14#include "library/trackcollection.h"14#include "library/trackcollection.h"
15#include "library/dao/trackdao.h"15#include "library/dao/trackdao.h"
1616
17BrowseFeature::BrowseFeature(QObject* parent, ConfigObject<ConfigValue>* pConfig,17BrowseFeature::BrowseFeature(QObject* parent,
18 ConfigObject<ConfigValue>* pConfig,
18 TrackCollection* pTrackCollection,19 TrackCollection* pTrackCollection,
19 RecordingManager* pRecordingManager)20 RecordingManager* pRecordingManager)
20 : LibraryFeature(parent),21 : LibraryFeature(parent),
@@ -22,44 +23,47 @@
22 m_browseModel(this, pTrackCollection, pRecordingManager),23 m_browseModel(this, pTrackCollection, pRecordingManager),
23 m_proxyModel(&m_browseModel),24 m_proxyModel(&m_browseModel),
24 m_pTrackCollection(pTrackCollection) {25 m_pTrackCollection(pTrackCollection) {
25
26 m_proxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);26 m_proxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);
27 m_proxyModel.setSortCaseSensitivity(Qt::CaseInsensitive);27 m_proxyModel.setSortCaseSensitivity(Qt::CaseInsensitive);
2828
29 //The invisible root item of the child model29 // The invisible root item of the child model
30 TreeItem* rootItem = new TreeItem();30 TreeItem* rootItem = new TreeItem();
3131
32 TreeItem* quick_link = new TreeItem(tr("Quick Links"), QUICK_LINK_NODE ,this , rootItem);32 TreeItem* quick_link = new TreeItem(
33 tr("Quick Links"), QUICK_LINK_NODE, this, rootItem);
33 rootItem->appendChild(quick_link);34 rootItem->appendChild(quick_link);
3435
35 //Create the 'devices' shortcut36 // Create the 'devices' shortcut
36#if defined(__WINDOWS__)37#if defined(__WINDOWS__)
37 TreeItem* devices_link = new TreeItem(tr("Devices"), DEVICE_NODE ,this , rootItem);38 TreeItem* devices_link = new TreeItem(
39 tr("Devices"), DEVICE_NODE, this, rootItem);
38 rootItem->appendChild(devices_link);40 rootItem->appendChild(devices_link);
39 //show drive letters41 // show drive letters
40 QFileInfoList drives = QDir::drives();42 QFileInfoList drives = QDir::drives();
41 //show drive letters43 // show drive letters
42 foreach(QFileInfo drive, drives){44 foreach (QFileInfo drive, drives) {
43 TreeItem* driveLetter = new TreeItem(45 TreeItem* driveLetter = new TreeItem(
44 drive.canonicalPath(), // displays C:46 drive.canonicalPath(), // displays C:
45 drive.filePath(), //Displays C:/47 drive.filePath(), // Displays C:/
46 this ,48 this ,
47 devices_link);49 devices_link);
48 devices_link->appendChild(driveLetter);50 devices_link->appendChild(driveLetter);
49 }51 }
50#elif defined(__APPLE__)52#elif defined(__APPLE__)
51 //Apple hides the base Linux file structure53 // Apple hides the base Linux file structure But all devices are mounted at
52 //But all devices are mounted at /Volumes54 // /Volumes
53 TreeItem* devices_link = new TreeItem(tr("Devices"), "/Volumes/", this , rootItem);55 TreeItem* devices_link = new TreeItem(
56 tr("Devices"), "/Volumes/", this, rootItem);
54 rootItem->appendChild(devices_link);57 rootItem->appendChild(devices_link);
55#else //LINUX58#else // LINUX
56 TreeItem* devices_link = new TreeItem(tr("Removable Devices"), "/media/", this , rootItem);59 TreeItem* devices_link = new TreeItem(
60 tr("Removable Devices"), "/media/", this, rootItem);
57 rootItem->appendChild(devices_link);61 rootItem->appendChild(devices_link);
5862
59 //show root directory on UNIX-based operating systems63 // show root directory on UNIX-based operating systems
60 TreeItem* root_folder_item = new TreeItem(QDir::rootPath(), QDir::rootPath(),this , rootItem);64 TreeItem* root_folder_item = new TreeItem(
65 QDir::rootPath(), QDir::rootPath(), this, rootItem);
61 rootItem->appendChild(root_folder_item);66 rootItem->appendChild(root_folder_item);
62
63#endif67#endif
6468
65 /*69 /*
@@ -76,34 +80,43 @@
76 * deletion.80 * deletion.
77 */81 */
7882
79 //Add a shortcut to the Music folder which Mixxx uses83 // Add a shortcut to the Music folder which Mixxx uses
80 QString mixxx_music_dir = m_pConfig->getValueString(ConfigKey("[Playlist]","Directory"));84 QString mixxx_music_dir = m_pConfig->getValueString(
81 QString os_music_folder_dir = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);85 ConfigKey("[Playlist]", "Directory"));
82 QString os_documents_folder_dir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);86 QString os_music_folder_dir = QDesktopServices::storageLocation(
83 QString os_home_folder_dir = QDesktopServices::storageLocation(QDesktopServices::HomeLocation);87 QDesktopServices::MusicLocation);
84 QString os_desktop_folder_dir = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);88 QString os_documents_folder_dir = QDesktopServices::storageLocation(
89 QDesktopServices::DocumentsLocation);
90 QString os_home_folder_dir = QDesktopServices::storageLocation(
91 QDesktopServices::HomeLocation);
92 QString os_desktop_folder_dir = QDesktopServices::storageLocation(
93 QDesktopServices::DesktopLocation);
8594
86 TreeItem* mixxx_library_dir_item = new TreeItem(tr("Mixxx Library"), mixxx_music_dir +"/" ,this , quick_link);95 TreeItem* mixxx_library_dir_item = new TreeItem(
96 tr("Mixxx Library"), mixxx_music_dir + "/", this, quick_link);
87 quick_link->appendChild(mixxx_library_dir_item);97 quick_link->appendChild(mixxx_library_dir_item);
8898
89 TreeItem*os_home_dir_item = new TreeItem(tr("Home"), os_home_folder_dir +"/" , this , quick_link);99 TreeItem* os_home_dir_item = new TreeItem(
100 tr("Home"), os_home_folder_dir + "/", this, quick_link);
90 quick_link->appendChild(os_home_dir_item);101 quick_link->appendChild(os_home_dir_item);
91102
92 TreeItem*os_music_dir_item = new TreeItem(tr("Music"), os_music_folder_dir +"/" , this , quick_link);103 TreeItem* os_music_dir_item = new TreeItem(
104 tr("Music"), os_music_folder_dir + "/", this, quick_link);
93 quick_link->appendChild(os_music_dir_item);105 quick_link->appendChild(os_music_dir_item);
94106
95 TreeItem*os_docs_dir_item = new TreeItem(tr("Documents"), os_documents_folder_dir +"/" , this , quick_link);107 TreeItem* os_docs_dir_item = new TreeItem(
108 tr("Documents"), os_documents_folder_dir + "/", this, quick_link);
96 quick_link->appendChild(os_docs_dir_item);109 quick_link->appendChild(os_docs_dir_item);
97110
98 TreeItem*os_desktop_dir_item = new TreeItem(tr("Desktop"), os_desktop_folder_dir +"/" , this , quick_link);111 TreeItem* os_desktop_dir_item = new TreeItem(
112 tr("Desktop"), os_desktop_folder_dir + "/", this, quick_link);
99 quick_link->appendChild(os_desktop_dir_item);113 quick_link->appendChild(os_desktop_dir_item);
100114
101 //initialize the model115 // initialize the model
102 m_childModel.setRootItem(rootItem);116 m_childModel.setRootItem(rootItem);
103}117}
104118
105BrowseFeature::~BrowseFeature() {119BrowseFeature::~BrowseFeature() {
106
107}120}
108121
109QVariant BrowseFeature::title() {122QVariant BrowseFeature::title() {
@@ -119,18 +132,24 @@
119}132}
120133
121bool BrowseFeature::dropAccept(QUrl url) {134bool BrowseFeature::dropAccept(QUrl url) {
135 Q_UNUSED(url);
122 return false;136 return false;
123}137}
124138
125bool BrowseFeature::dropAcceptChild(const QModelIndex& index, QUrl url) {139bool BrowseFeature::dropAcceptChild(const QModelIndex& index, QUrl url) {
140 Q_UNUSED(index);
141 Q_UNUSED(url);
126 return false;142 return false;
127}143}
128144
129bool BrowseFeature::dragMoveAccept(QUrl url) {145bool BrowseFeature::dragMoveAccept(QUrl url) {
146 Q_UNUSED(url);
130 return false;147 return false;
131}148}
132149
133bool BrowseFeature::dragMoveAcceptChild(const QModelIndex& index, QUrl url) {150bool BrowseFeature::dragMoveAcceptChild(const QModelIndex& index, QUrl url) {
151 Q_UNUSED(index);
152 Q_UNUSED(url);
134 return false;153 return false;
135}154}
136155
@@ -143,59 +162,64 @@
143 */162 */
144void BrowseFeature::activateChild(const QModelIndex& index) {163void BrowseFeature::activateChild(const QModelIndex& index) {
145 TreeItem *item = static_cast<TreeItem*>(index.internalPointer());164 TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
146 qDebug() << "BrowseFeature::activateChild " << item->data() << " " << item->dataPath();165 qDebug() << "BrowseFeature::activateChild " << item->data() << " "
166 << item->dataPath();
147 m_browseModel.setPath(item->dataPath().toString());167 m_browseModel.setPath(item->dataPath().toString());
148 emit(showTrackModel(&m_proxyModel));168 emit(showTrackModel(&m_proxyModel));
149
150}169}
151170
152void BrowseFeature::onRightClick(const QPoint& globalPos) {171void BrowseFeature::onRightClick(const QPoint& globalPos) {
153}172 Q_UNUSED(globalPos);
154173}
155void BrowseFeature::onRightClickChild(const QPoint& globalPos, QModelIndex index) {174
156}175void BrowseFeature::onRightClickChild(const QPoint& globalPos,
176 QModelIndex index) {
177 Q_UNUSED(globalPos);
178 Q_UNUSED(index);
179}
180
157/*181/*
158 * This is called whenever you double click or use the triangle symbol to expand182 * This is called whenever you double click or use the triangle symbol to expand
159 * the subtree. The method will read the subfolders.183 * the subtree. The method will read the subfolders.
160 */184 */
161void BrowseFeature::onLazyChildExpandation(const QModelIndex &index){185void BrowseFeature::onLazyChildExpandation(const QModelIndex &index){
162 TreeItem *item = static_cast<TreeItem*>(index.internalPointer());186 TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
163 qDebug() << "BrowseFeature::onLazyChildExpandation " << item->data() << " " << item->dataPath();187 qDebug() << "BrowseFeature::onLazyChildExpandation " << item->data()
188 << " " << item->dataPath();
164189
165 // If the item is a build-in node, e.g., 'QuickLink' return190 // If the item is a build-in node, e.g., 'QuickLink' return
166 if(item->dataPath().toString() == QUICK_LINK_NODE)191 if (item->dataPath().toString() == QUICK_LINK_NODE) {
167 return;192 return;
193 }
168194
169 //Before we populate the subtree, we need to delete old subtrees195 // Before we populate the subtree, we need to delete old subtrees
170 m_childModel.removeRows(0, item->childCount(), index);196 m_childModel.removeRows(0, item->childCount(), index);
171197
172 // List of subfolders or drive letters198 // List of subfolders or drive letters
173 QList<TreeItem*> folders;199 QList<TreeItem*> folders;
174200
175 // If we are on the special device node201 // If we are on the special device node
176 if(item->dataPath().toString() == DEVICE_NODE){202 if (item->dataPath().toString() == DEVICE_NODE) {
177 //Repopulate drive list203 // Repopulate drive list
178 QFileInfoList drives = QDir::drives();204 QFileInfoList drives = QDir::drives();
179 //show drive letters205 // show drive letters
180 foreach(QFileInfo drive, drives){206 foreach (QFileInfo drive, drives) {
181 TreeItem* driveLetter = new TreeItem(207 TreeItem* driveLetter = new TreeItem(
182 drive.canonicalPath(), // displays C:208 drive.canonicalPath(), // displays C:
183 drive.filePath(), //Displays C:/209 drive.filePath(), //Displays C:/
184 this ,210 this ,
185 item);211 item);
186 folders << driveLetter;212 folders << driveLetter;
187 }213 }
188214 } else { // we assume that the path refers to a folder in the file system
189 }215 // populate childs
190 else // we assume that the path refers to a folder in the file system
191 {
192 //populate childs
193 QDir dir(item->dataPath().toString());216 QDir dir(item->dataPath().toString());
194 QFileInfoList all = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);217 QFileInfoList all = dir.entryInfoList(
218 QDir::Dirs | QDir::NoDotAndDotDot);
195219
196 // loop through all the item and construct the childs220 // loop through all the item and construct the childs
197 foreach(QFileInfo one, all){221 foreach (QFileInfo one, all) {
198 //Skip folders that end with .app on OS X222 // Skip folders that end with .app on OS X
199#if defined(__APPLE__)223#if defined(__APPLE__)
200 if (one.isDir() && one.fileName().endsWith(".app"))224 if (one.isDir() && one.fileName().endsWith(".app"))
201 continue;225 continue;
@@ -203,15 +227,17 @@
203 // We here create new items for the sidebar models227 // We here create new items for the sidebar models
204 // Once the items are added to the TreeItemModel,228 // Once the items are added to the TreeItemModel,
205 // the models takes ownership of them and ensures their deletion229 // the models takes ownership of them and ensures their deletion
206 TreeItem* folder = new TreeItem(one.fileName(),230 TreeItem* folder = new TreeItem(
207 item->dataPath().toString().append(one.fileName() +"/"),231 one.fileName(),
208 this,232 item->dataPath().toString().append(one.fileName() +"/"),
209 item);233 this, item);
210 folders << folder;234 folders << folder;
211 }235 }
212 }236 }
213 //we need to check here if subfolders are found237 // we need to check here if subfolders are found
214 //On Ubuntu 10.04, otherwise, this will draw an icon although the folder has no subfolders238 // On Ubuntu 10.04, otherwise, this will draw an icon although the folder
215 if(!folders.isEmpty())239 // has no subfolders
216 m_childModel.insertRows(folders, 0, folders.size() , index);240 if (!folders.isEmpty()) {
241 m_childModel.insertRows(folders, 0, folders.size() , index);
242 }
217}243}
218244
=== modified file 'mixxx/src/library/browse/browsefeature.h'
--- mixxx/src/library/browse/browsefeature.h 2011-03-30 21:53:33 +0000
+++ mixxx/src/library/browse/browsefeature.h 2012-03-12 04:06:20 +0000
@@ -44,8 +44,8 @@
44 void onRightClickChild(const QPoint& globalPos, QModelIndex index);44 void onRightClickChild(const QPoint& globalPos, QModelIndex index);
4545
46 void onLazyChildExpandation(const QModelIndex& index);46 void onLazyChildExpandation(const QModelIndex& index);
47 47
48 signals:48 signals:
49 void setRootIndex(const QModelIndex&);49 void setRootIndex(const QModelIndex&);
5050
51 private:51 private:
5252
=== modified file 'mixxx/src/library/browse/browsetablemodel.cpp'
--- mixxx/src/library/browse/browsetablemodel.cpp 2011-12-28 20:30:15 +0000
+++ mixxx/src/library/browse/browsetablemodel.cpp 2012-03-12 04:06:20 +0000
@@ -16,13 +16,14 @@
16#include "audiotagger.h"16#include "audiotagger.h"
1717
1818
19BrowseTableModel::BrowseTableModel(QObject* parent, TrackCollection* pTrackCollection,19BrowseTableModel::BrowseTableModel(QObject* parent,
20 TrackCollection* pTrackCollection,
20 RecordingManager* pRecordingManager)21 RecordingManager* pRecordingManager)
21 : TrackModel(pTrackCollection->getDatabase(), // TrackCollections m_db (defaultConnection)22 : TrackModel(pTrackCollection->getDatabase(),
22 "mixxx.db.model.browse"),23 "mixxx.db.model.browse"),
23 QStandardItemModel(parent),24 QStandardItemModel(parent),
24 m_pTrackCollection(pTrackCollection),25 m_pTrackCollection(pTrackCollection),
25 m_pRecordingManager(pRecordingManager) {26 m_pRecordingManager(pRecordingManager) {
26 QStringList header_data;27 QStringList header_data;
27 header_data.insert(COLUMN_FILENAME, tr("Filename"));28 header_data.insert(COLUMN_FILENAME, tr("Filename"));
28 header_data.insert(COLUMN_ARTIST, tr("Artist"));29 header_data.insert(COLUMN_ARTIST, tr("Artist"));
@@ -50,23 +51,24 @@
50 addSearchColumn(COLUMN_COMMENT);51 addSearchColumn(COLUMN_COMMENT);
5152
52 setHorizontalHeaderLabels(header_data);53 setHorizontalHeaderLabels(header_data);
53 //register the QList<T> as a metatype since we use QueuedConnection below54 // register the QList<T> as a metatype since we use QueuedConnection below
54 qRegisterMetaType< QList< QList<QStandardItem*> > >("QList< QList<QStandardItem*> >");55 qRegisterMetaType< QList< QList<QStandardItem*> > >(
56 "QList< QList<QStandardItem*> >");
55 qRegisterMetaType<BrowseTableModel*>("BrowseTableModel*");57 qRegisterMetaType<BrowseTableModel*>("BrowseTableModel*");
5658
57 connect(BrowseThread::getInstance(), SIGNAL(clearModel(BrowseTableModel*)),59 connect(BrowseThread::getInstance(), SIGNAL(clearModel(BrowseTableModel*)),
58 this, SLOT(slotClear(BrowseTableModel*)),60 this, SLOT(slotClear(BrowseTableModel*)),
59 Qt::QueuedConnection);61 Qt::QueuedConnection);
6062
61 connect(BrowseThread::getInstance(), SIGNAL(rowsAppended(const QList< QList<QStandardItem*> >&, BrowseTableModel*)),63 connect(
62 this, SLOT(slotInsert(const QList< QList<QStandardItem*> >&, BrowseTableModel*)),64 BrowseThread::getInstance(),
63 Qt::QueuedConnection);65 SIGNAL(rowsAppended(const QList< QList<QStandardItem*> >&, BrowseTableModel*)),
6466 this,
67 SLOT(slotInsert(const QList< QList<QStandardItem*> >&, BrowseTableModel*)),
68 Qt::QueuedConnection);
65}69}
6670
67BrowseTableModel::~BrowseTableModel()71BrowseTableModel::~BrowseTableModel() {
68{
69
70}72}
7173
72const QList<int>& BrowseTableModel::searchColumns() const {74const QList<int>& BrowseTableModel::searchColumns() const {
@@ -77,20 +79,19 @@
77 m_searchColumns.push_back(index);79 m_searchColumns.push_back(index);
78}80}
7981
80void BrowseTableModel::setPath(QString absPath)82void BrowseTableModel::setPath(QString absPath) {
81{
82 m_current_path = absPath;83 m_current_path = absPath;
83 BrowseThread::getInstance()->executePopulation(m_current_path, this);84 BrowseThread::getInstance()->executePopulation(m_current_path, this);
84
85}85}
8686
87TrackPointer BrowseTableModel::getTrack(const QModelIndex& index) const87TrackPointer BrowseTableModel::getTrack(const QModelIndex& index) const {
88{
89 QString track_location = getTrackLocation(index);88 QString track_location = getTrackLocation(index);
90 if(m_pRecordingManager->getRecordingLocation() == track_location) {89 if (m_pRecordingManager->getRecordingLocation() == track_location) {
91 QMessageBox::critical(0, tr("Mixxx Library"),tr("Could not load the following file because"90 QMessageBox::critical(
92 " it is in use by Mixxx or another application.")91 0, tr("Mixxx Library"),
93 + "\n" +track_location);92 tr("Could not load the following file because"
93 " it is in use by Mixxx or another application.")
94 + "\n" +track_location);
94 return TrackPointer();95 return TrackPointer();
95 }96 }
9697
@@ -104,29 +105,27 @@
104 return track_dao.getTrack(track_id);105 return track_dao.getTrack(track_id);
105}106}
106107
107QString BrowseTableModel::getTrackLocation(const QModelIndex& index) const108QString BrowseTableModel::getTrackLocation(const QModelIndex& index) const {
108{
109 int row = index.row();109 int row = index.row();
110110
111 QModelIndex index2 = this->index(row, COLUMN_LOCATION);111 QModelIndex index2 = this->index(row, COLUMN_LOCATION);
112 return data(index2).toString();112 return data(index2).toString();
113
114}113}
115114
116int BrowseTableModel::getTrackId(const QModelIndex& index) const {115int BrowseTableModel::getTrackId(const QModelIndex& index) const {
117 Q_UNUSED(index);116 Q_UNUSED(index);
118 // We can't implement this as it stands.117 // We can't implement this as it stands.
119 return -1;118 return -1;
120}119}
121120
122const QLinkedList<int> BrowseTableModel::getTrackRows(int trackId) const {121const QLinkedList<int> BrowseTableModel::getTrackRows(int trackId) const {
123 Q_UNUSED(trackId);122 Q_UNUSED(trackId);
124 // We can't implement this as it stands.123 // We can't implement this as it stands.
125 return QLinkedList<int>();124 return QLinkedList<int>();
126}125}
127126
128void BrowseTableModel::search(const QString& searchText) {127void BrowseTableModel::search(const QString& searchText) {
129 Q_UNUSED(searchText);128 Q_UNUSED(searchText);
130}129}
131130
132const QString BrowseTableModel::currentSearch() const {131const QString BrowseTableModel::currentSearch() const {
@@ -142,16 +141,14 @@
142}141}
143142
144void BrowseTableModel::moveTrack(const QModelIndex&, const QModelIndex&) {143void BrowseTableModel::moveTrack(const QModelIndex&, const QModelIndex&) {
145
146}144}
147145
148QItemDelegate* BrowseTableModel::delegateForColumn(const int) {146QItemDelegate* BrowseTableModel::delegateForColumn(const int) {
149 return NULL;147 return NULL;
150}148}
151149
152void BrowseTableModel::removeTrack(const QModelIndex& index)150void BrowseTableModel::removeTrack(const QModelIndex& index) {
153{151 if (!index.isValid()) {
154 if(!index.isValid()) {
155 return;152 return;
156 }153 }
157 QStringList trackLocations;154 QStringList trackLocations;
@@ -159,8 +156,7 @@
159 removeTracks(trackLocations);156 removeTracks(trackLocations);
160}157}
161158
162void BrowseTableModel::removeTracks(const QModelIndexList& indices)159void BrowseTableModel::removeTracks(const QModelIndexList& indices) {
163{
164 QStringList trackLocations;160 QStringList trackLocations;
165 foreach (QModelIndex index, indices) {161 foreach (QModelIndex index, indices) {
166 if (!index.isValid()) {162 if (!index.isValid()) {
@@ -176,11 +172,12 @@
176 return;172 return;
177173
178 // Ask user if s/he is sure174 // Ask user if s/he is sure
179 if (QMessageBox::question(NULL, tr("Mixxx Library"),175 if (QMessageBox::question(
180 tr("Warning: This will permanently delete the following files:")176 NULL, tr("Mixxx Library"),
181 + "\n" + trackLocations.join("\n") + "\n" +177 tr("Warning: This will permanently delete the following files:")
182 tr("Are you sure you want to delete these files from your computer?"),178 + "\n" + trackLocations.join("\n") + "\n" +
183 QMessageBox::Yes, QMessageBox::Abort) == QMessageBox::Abort) {179 tr("Are you sure you want to delete these files from your computer?"),
180 QMessageBox::Yes, QMessageBox::Abort) == QMessageBox::Abort) {
184 return;181 return;
185 }182 }
186183
@@ -191,8 +188,10 @@
191 foreach (QString track_location, trackLocations) {188 foreach (QString track_location, trackLocations) {
192 // If track is in use or deletion fails, show an error message.189 // If track is in use or deletion fails, show an error message.
193 if (isTrackInUse(track_location) || !QFile::remove(track_location)) {190 if (isTrackInUse(track_location) || !QFile::remove(track_location)) {
194 QMessageBox::critical(0, tr("Mixxx Library"),tr("Could not delete the following file because"191 QMessageBox::critical(
195 " it is in use by Mixxx or another application:") + "\n" +track_location);192 0, tr("Mixxx Library"),
193 tr("Could not delete the following file because"
194 " it is in use by Mixxx or another application:") + "\n" +track_location);
196 continue;195 continue;
197 }196 }
198197
@@ -213,20 +212,19 @@
213 }212 }
214}213}
215214
216bool BrowseTableModel::addTrack(const QModelIndex& index, QString location)215bool BrowseTableModel::addTrack(const QModelIndex& index, QString location) {
217{
218 Q_UNUSED(index);216 Q_UNUSED(index);
219 Q_UNUSED(location);217 Q_UNUSED(location);
220 return false;218 return false;
221}219}
222220
223QMimeData* BrowseTableModel::mimeData(const QModelIndexList &indexes) const {221QMimeData* BrowseTableModel::mimeData(const QModelIndexList &indexes) const {
224 QMimeData *mimeData = new QMimeData();222 QMimeData *mimeData = new QMimeData();
225 QList<QUrl> urls;223 QList<QUrl> urls;
226224
227 //Ok, so the list of indexes we're given contains separates indexes for225 // Ok, so the list of indexes we're given contains separates indexes for
228 //each column, so even if only one row is selected, we'll have like 7 indexes.226 // each column, so even if only one row is selected, we'll have like 7
229 //We need to only count each row once:227 // indexes. We need to only count each row once:
230 QList<int> rows;228 QList<int> rows;
231229
232 foreach (QModelIndex index, indexes) {230 foreach (QModelIndex index, indexes) {
@@ -234,9 +232,9 @@
234 if (!rows.contains(index.row())) {232 if (!rows.contains(index.row())) {
235 rows.push_back(index.row());233 rows.push_back(index.row());
236 QUrl url = QUrl::fromLocalFile(getTrackLocation(index));234 QUrl url = QUrl::fromLocalFile(getTrackLocation(index));
237 if (!url.isValid())235 if (!url.isValid()) {
238 qDebug() << "ERROR invalid url\n";236 qDebug() << "ERROR invalid url\n";
239 else {237 } else {
240 urls.append(url);238 urls.append(url);
241 qDebug() << "Appending URL:" << url;239 qDebug() << "Appending URL:" << url;
242 }240 }
@@ -247,22 +245,23 @@
247 return mimeData;245 return mimeData;
248}246}
249247
250void BrowseTableModel::slotClear(BrowseTableModel* caller_object)248void BrowseTableModel::slotClear(BrowseTableModel* caller_object) {
251{249 if (caller_object == this) {
252 if(caller_object == this)
253 removeRows(0, rowCount());250 removeRows(0, rowCount());
251 }
254}252}
255253
256void BrowseTableModel::slotInsert(const QList< QList<QStandardItem*> >& rows, BrowseTableModel* caller_object) {254void BrowseTableModel::slotInsert(const QList< QList<QStandardItem*> >& rows,
257 //There exists more than one BrowseTableModel in Mixxx255 BrowseTableModel* caller_object) {
258 //We only want to receive items here, this object has 'ordered' by the BrowserThread (singleton)256 // There exists more than one BrowseTableModel in Mixxx We only want to
259 if(caller_object == this) {257 // receive items here, this object has 'ordered' by the BrowserThread
258 // (singleton)
259 if (caller_object == this) {
260 //qDebug() << "BrowseTableModel::slotInsert";260 //qDebug() << "BrowseTableModel::slotInsert";
261 for(int i=0; i < rows.size(); ++i) {261 for (int i = 0; i < rows.size(); ++i) {
262 appendRow(rows.at(i));262 appendRow(rows.at(i));
263 }263 }
264 }264 }
265
266}265}
267266
268TrackModel::CapabilitiesFlags BrowseTableModel::getCapabilities() const {267TrackModel::CapabilitiesFlags BrowseTableModel::getCapabilities() const {
@@ -275,106 +274,108 @@
275 | TRACKMODELCAPS_LOADTOSAMPLER;274 | TRACKMODELCAPS_LOADTOSAMPLER;
276}275}
277276
278Qt::ItemFlags BrowseTableModel::flags(const QModelIndex &index) const{277Qt::ItemFlags BrowseTableModel::flags(const QModelIndex &index) const {
279
280 Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);278 Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);
281279
282 //Enable dragging songs from this data model to elsewhere (like the waveform280 // Enable dragging songs from this data model to elsewhere (like the
283 //widget to load a track into a Player).281 // waveform widget to load a track into a Player).
284 defaultFlags |= Qt::ItemIsDragEnabled;282 defaultFlags |= Qt::ItemIsDragEnabled;
285283
286 QString track_location = getTrackLocation(index);284 QString track_location = getTrackLocation(index);
287 int column = index.column();285 int column = index.column();
288286
289 if(isTrackInUse(track_location) ||287 if (isTrackInUse(track_location) ||
290 column == COLUMN_FILENAME ||288 column == COLUMN_FILENAME ||
291 column == COLUMN_BITRATE ||289 column == COLUMN_BITRATE ||
292 column == COLUMN_DURATION ||290 column == COLUMN_DURATION ||
293 column == COLUMN_TYPE) {291 column == COLUMN_TYPE) {
294 return defaultFlags;292 return defaultFlags;
295 }293 } else {
296 else{
297 return defaultFlags | Qt::ItemIsEditable;294 return defaultFlags | Qt::ItemIsEditable;
298 }295 }
299}296}
300297
301bool BrowseTableModel::isTrackInUse(QString &track_location) const298bool BrowseTableModel::isTrackInUse(const QString &track_location) const {
302{299 int decks = ControlObject::getControl(
303 int decks = ControlObject::getControl(ConfigKey("[Master]","num_decks"))->get();300 ConfigKey("[Master]", "num_decks"))->get();
304 //check if file is loaded to a deck301 // check if file is loaded to a deck
305 for(int i=1; i <= decks; ++i) {302 for (int i = 1; i <= decks; ++i) {
306 TrackPointer loaded_track = PlayerInfo::Instance().getTrackInfo(QString("[Channel%1]").arg(i));303 TrackPointer loaded_track = PlayerInfo::Instance().getTrackInfo(
307 if(loaded_track && (loaded_track->getLocation() == track_location)) {304 QString("[Channel%1]").arg(i));
305 if (loaded_track && (loaded_track->getLocation() == track_location)) {
308 return true;306 return true;
309 }307 }
310 }308 }
311309
312 if(m_pRecordingManager->getRecordingLocation() == track_location) {310 if (m_pRecordingManager->getRecordingLocation() == track_location) {
313 return true;311 return true;
314 }312 }
315313
316 return false;314 return false;
317}315}
318316
319bool BrowseTableModel::setData(const QModelIndex &index, const QVariant &value, int role)317bool BrowseTableModel::setData(const QModelIndex &index, const QVariant &value,
320{318 int role) {
321 Q_UNUSED(role);319 Q_UNUSED(role);
322320
323 if(!index.isValid())321 if (!index.isValid()) {
324 return false;322 return false;
323 }
325 qDebug() << "BrowseTableModel::setData(" << index.data() << ")";324 qDebug() << "BrowseTableModel::setData(" << index.data() << ")";
326 int row = index.row();325 int row = index.row();
327 int col = index.column();326 int col = index.column();
328 QString track_location = getTrackLocation(index);327 QString track_location = getTrackLocation(index);
329 AudioTagger tagger(track_location);328 AudioTagger tagger(track_location);
330329
331 //set tagger information330 // set tagger information
332 tagger.setArtist(this->index(row,COLUMN_ARTIST).data().toString());331 tagger.setArtist(this->index(row, COLUMN_ARTIST).data().toString());
333 tagger.setTitle(this->index(row,COLUMN_TITLE).data().toString());332 tagger.setTitle(this->index(row, COLUMN_TITLE).data().toString());
334 tagger.setAlbum(this->index(row,COLUMN_ALBUM).data().toString());333 tagger.setAlbum(this->index(row, COLUMN_ALBUM).data().toString());
335 tagger.setKey(this->index(row,COLUMN_KEY).data().toString());334 tagger.setKey(this->index(row, COLUMN_KEY).data().toString());
336 tagger.setBpm(this->index(row,COLUMN_BPM).data().toString());335 tagger.setBpm(this->index(row, COLUMN_BPM).data().toString());
337 tagger.setComment(this->index(row,COLUMN_COMMENT).data().toString());336 tagger.setComment(this->index(row, COLUMN_COMMENT).data().toString());
338 tagger.setTracknumber(this->index(row,COLUMN_TRACK_NUMBER).data().toString());337 tagger.setTracknumber(
339 tagger.setYear(this->index(row,COLUMN_YEAR).data().toString());338 this->index(row, COLUMN_TRACK_NUMBER).data().toString());
340 tagger.setGenre(this->index(row,COLUMN_GENRE).data().toString());339 tagger.setYear(this->index(row, COLUMN_YEAR).data().toString());
341 tagger.setComposer(this->index(row,COLUMN_COMPOSER).data().toString());340 tagger.setGenre(this->index(row, COLUMN_GENRE).data().toString());
341 tagger.setComposer(this->index(row, COLUMN_COMPOSER).data().toString());
342342
343 //check if one the item were edited343 // check if one the item were edited
344 if(col == COLUMN_ARTIST) {344 if (col == COLUMN_ARTIST) {
345 tagger.setArtist(value.toString());345 tagger.setArtist(value.toString());
346 } else if(col == COLUMN_TITLE) {346 } else if (col == COLUMN_TITLE) {
347 tagger.setTitle(value.toString());347 tagger.setTitle(value.toString());
348 } else if(col == COLUMN_ALBUM) {348 } else if (col == COLUMN_ALBUM) {
349 tagger.setAlbum(value.toString());349 tagger.setAlbum(value.toString());
350 } else if(col == COLUMN_BPM) {350 } else if (col == COLUMN_BPM) {
351 tagger.setBpm(value.toString());351 tagger.setBpm(value.toString());
352 } else if(col == COLUMN_KEY) {352 } else if (col == COLUMN_KEY) {
353 tagger.setKey(value.toString());353 tagger.setKey(value.toString());
354 } else if(col == COLUMN_TRACK_NUMBER) {354 } else if (col == COLUMN_TRACK_NUMBER) {
355 tagger.setTracknumber(value.toString());355 tagger.setTracknumber(value.toString());
356 } else if(col == COLUMN_COMMENT) {356 } else if (col == COLUMN_COMMENT) {
357 tagger.setComment(value.toString());357 tagger.setComment(value.toString());
358 } else if(col == COLUMN_GENRE) {358 } else if (col == COLUMN_GENRE) {
359 tagger.setGenre(value.toString());359 tagger.setGenre(value.toString());
360 } else if(col == COLUMN_COMPOSER) {360 } else if (col == COLUMN_COMPOSER) {
361 tagger.setComposer(value.toString());361 tagger.setComposer(value.toString());
362 } else if(col == COLUMN_YEAR) {362 } else if (col == COLUMN_YEAR) {
363 tagger.setYear(value.toString());363 tagger.setYear(value.toString());
364 }364 }
365365
366366
367 QStandardItem* item = itemFromIndex(index);367 QStandardItem* item = itemFromIndex(index);
368 if(tagger.save()) {368 if (tagger.save()) {
369 //Modify underlying interalPointer object369 // Modify underlying interalPointer object
370 item->setText(value.toString());370 item->setText(value.toString());
371 return true;371 return true;
372 }372 } else {
373 else {373 // reset to old value in error
374 //reset to old value in error
375 item->setText(index.data().toString());374 item->setText(index.data().toString());
376 QMessageBox::critical(0, tr("Mixxx Library"),tr("Could not update file metadata.")375 QMessageBox::critical(
377 + "\n" +track_location);376 0, tr("Mixxx Library"),
377 tr("Could not update file metadata.")
378 + "\n" +track_location);
378 return false;379 return false;
379 }380 }
380}381}
381382
=== modified file 'mixxx/src/library/browse/browsetablemodel.h'
--- mixxx/src/library/browse/browsetablemodel.h 2012-01-07 05:48:41 +0000
+++ mixxx/src/library/browse/browsetablemodel.h 2012-03-12 04:06:20 +0000
@@ -66,7 +66,7 @@
66 void removeTracks(QStringList trackLocations);66 void removeTracks(QStringList trackLocations);
6767
68 void addSearchColumn(int index);68 void addSearchColumn(int index);
69 bool isTrackInUse(QString& file) const;69 bool isTrackInUse(const QString& file) const;
70 QList<int> m_searchColumns;70 QList<int> m_searchColumns;
71 QString m_current_path;71 QString m_current_path;
72 TrackCollection* m_pTrackCollection;72 TrackCollection* m_pTrackCollection;
7373
=== modified file 'mixxx/src/library/dao/cratedao.h'
--- mixxx/src/library/dao/cratedao.h 2011-10-21 00:42:23 +0000
+++ mixxx/src/library/dao/cratedao.h 2012-03-12 04:06:20 +0000
@@ -47,6 +47,8 @@
47 void changed(int crateId);47 void changed(int crateId);
48 void trackAdded(int crateId, int trackId);48 void trackAdded(int crateId, int trackId);
49 void trackRemoved(int crateId, int trackId);49 void trackRemoved(int crateId, int trackId);
50 void renamed(int crateId);
51 void lockChanged(int crateId);
5052
51 private:53 private:
52 QSqlDatabase& m_database;54 QSqlDatabase& m_database;
5355
=== modified file 'mixxx/src/widget/wtracktableview.cpp'
--- mixxx/src/widget/wtracktableview.cpp 2011-12-14 17:22:49 +0000
+++ mixxx/src/widget/wtracktableview.cpp 2012-03-12 04:06:20 +0000
@@ -82,6 +82,7 @@
8282
83 delete m_pReloadMetadataAct;83 delete m_pReloadMetadataAct;
84 delete m_pAutoDJAct;84 delete m_pAutoDJAct;
85 delete m_pAutoDJTopAct;
85 delete m_pRemoveAct;86 delete m_pRemoveAct;
86 delete m_pPropertiesAct;87 delete m_pPropertiesAct;
87 delete m_pMenu;88 delete m_pMenu;
@@ -241,7 +242,8 @@
241void WTrackTableView::disableSorting() {242void WTrackTableView::disableSorting() {
242 // We have to manually do this because setSortingEnabled(false) does not243 // We have to manually do this because setSortingEnabled(false) does not
243 // properly disconnect the signals for some reason.244 // properly disconnect the signals for some reason.
244 disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),245 disconnect(horizontalHeader(),
246 SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
245 this, SLOT(doSortByColumn(int)));247 this, SLOT(doSortByColumn(int)));
246 horizontalHeader()->setSortIndicatorShown(false);248 horizontalHeader()->setSortIndicatorShown(false);
247}249}
@@ -250,17 +252,23 @@
250 Q_ASSERT(m_pMenu);252 Q_ASSERT(m_pMenu);
251 Q_ASSERT(m_pSamplerMenu);253 Q_ASSERT(m_pSamplerMenu);
252254
253 m_pRemoveAct = new QAction(tr("Remove"),this);255 m_pRemoveAct = new QAction(tr("Remove"), this);
254 connect(m_pRemoveAct, SIGNAL(triggered()), this, SLOT(slotRemove()));256 connect(m_pRemoveAct, SIGNAL(triggered()), this, SLOT(slotRemove()));
255257
256 m_pPropertiesAct = new QAction(tr("Properties..."), this);258 m_pPropertiesAct = new QAction(tr("Properties..."), this);
257 connect(m_pPropertiesAct, SIGNAL(triggered()), this, SLOT(slotShowTrackInfo()));259 connect(m_pPropertiesAct, SIGNAL(triggered()),
260 this, SLOT(slotShowTrackInfo()));
258261
259 m_pAutoDJAct = new QAction(tr("Add to Auto DJ Queue"),this);262 m_pAutoDJAct = new QAction(tr("Add to Auto-DJ Queue (bottom)"), this);
260 connect(m_pAutoDJAct, SIGNAL(triggered()), this, SLOT(slotSendToAutoDJ()));263 connect(m_pAutoDJAct, SIGNAL(triggered()), this, SLOT(slotSendToAutoDJ()));
261264
265 m_pAutoDJTopAct = new QAction(tr("Add to Auto-DJ Queue (top)"), this);
266 connect(m_pAutoDJTopAct, SIGNAL(triggered()),
267 this, SLOT(slotSendToAutoDJTop()));
268
262 m_pReloadMetadataAct = new QAction(tr("Reload Track Metadata"), this);269 m_pReloadMetadataAct = new QAction(tr("Reload Track Metadata"), this);
263 connect(m_pReloadMetadataAct, SIGNAL(triggered()), this, SLOT(slotReloadTrackMetadata()));270 connect(m_pReloadMetadataAct, SIGNAL(triggered()),
271 this, SLOT(slotReloadTrackMetadata()));
264}272}
265273
266void WTrackTableView::slotMouseDoubleClicked(const QModelIndex &index) {274void WTrackTableView::slotMouseDoubleClicked(const QModelIndex &index) {
@@ -345,8 +353,7 @@
345 m_pTrackInfo->show();353 m_pTrackInfo->show();
346}354}
347355
348void WTrackTableView::contextMenuEvent(QContextMenuEvent * event)356void WTrackTableView::contextMenuEvent(QContextMenuEvent* event) {
349{
350 QModelIndexList indices = selectionModel()->selectedRows();357 QModelIndexList indices = selectionModel()->selectedRows();
351358
352 // Gray out some stuff if multiple songs were selected.359 // Gray out some stuff if multiple songs were selected.
@@ -356,6 +363,7 @@
356363
357 if (modelHasCapabilities(TrackModel::TRACKMODELCAPS_ADDTOAUTODJ)) {364 if (modelHasCapabilities(TrackModel::TRACKMODELCAPS_ADDTOAUTODJ)) {
358 m_pMenu->addAction(m_pAutoDJAct);365 m_pMenu->addAction(m_pAutoDJAct);
366 m_pMenu->addAction(m_pAutoDJTopAct);
359 m_pMenu->addSeparator();367 m_pMenu->addSeparator();
360 }368 }
361369
@@ -800,6 +808,15 @@
800}808}
801809
802void WTrackTableView::slotSendToAutoDJ() {810void WTrackTableView::slotSendToAutoDJ() {
811 // append to auto DJ
812 sendToAutoDJ(false); // bTop = false
813}
814
815void WTrackTableView::slotSendToAutoDJTop() {
816 sendToAutoDJ(true); // bTop = true
817}
818
819void WTrackTableView::sendToAutoDJ(bool bTop) {
803 if (!modelHasCapabilities(TrackModel::TRACKMODELCAPS_ADDTOAUTODJ)) {820 if (!modelHasCapabilities(TrackModel::TRACKMODELCAPS_ADDTOAUTODJ)) {
804 return;821 return;
805 }822 }
@@ -819,7 +836,15 @@
819 (pTrack = trackModel->getTrack(index))) {836 (pTrack = trackModel->getTrack(index))) {
820 int iTrackId = pTrack->getId();837 int iTrackId = pTrack->getId();
821 if (iTrackId != -1) {838 if (iTrackId != -1) {
822 playlistDao.appendTrackToPlaylist(iTrackId, iAutoDJPlaylistId);839 if (bTop) {
840 // Load track to position two because position one is
841 // already loaded to the player
842 playlistDao.insertTrackIntoPlaylist(iTrackId,
843 iAutoDJPlaylistId, 2);
844 } else {
845 playlistDao.appendTrackToPlaylist(
846 iTrackId, iAutoDJPlaylistId);
847 }
823 }848 }
824 }849 }
825 }850 }
826851
=== modified file 'mixxx/src/widget/wtracktableview.h'
--- mixxx/src/widget/wtracktableview.h 2011-10-14 03:58:14 +0000
+++ mixxx/src/widget/wtracktableview.h 2012-03-12 04:06:20 +0000
@@ -19,10 +19,9 @@
19const QString LIBRARY_CONFIGVALUE = "[Library]"; /** ConfigValue "value" (wtf) for library stuff */19const QString LIBRARY_CONFIGVALUE = "[Library]"; /** ConfigValue "value" (wtf) for library stuff */
2020
2121
22class WTrackTableView : public WLibraryTableView22class WTrackTableView : public WLibraryTableView {
23{
24 Q_OBJECT23 Q_OBJECT
25 public:24 public:
26 WTrackTableView(QWidget* parent, ConfigObject<ConfigValue>* pConfig,25 WTrackTableView(QWidget* parent, ConfigObject<ConfigValue>* pConfig,
27 TrackCollection* pTrackCollection);26 TrackCollection* pTrackCollection);
28 virtual ~WTrackTableView();27 virtual ~WTrackTableView();
@@ -46,6 +45,7 @@
46 void slotNextTrackInfo();45 void slotNextTrackInfo();
47 void slotPrevTrackInfo();46 void slotPrevTrackInfo();
48 void slotSendToAutoDJ();47 void slotSendToAutoDJ();
48 void slotSendToAutoDJTop();
49 void slotReloadTrackMetadata();49 void slotReloadTrackMetadata();
50 void addSelectionToPlaylist(int iPlaylistId);50 void addSelectionToPlaylist(int iPlaylistId);
51 void addSelectionToCrate(int iCrateId);51 void addSelectionToCrate(int iCrateId);
@@ -53,6 +53,7 @@
53 void doSortByColumn(int headerSection);53 void doSortByColumn(int headerSection);
5454
55 private:55 private:
56 void sendToAutoDJ(bool bTop);
56 void showTrackInfo(QModelIndex index);57 void showTrackInfo(QModelIndex index);
57 void createActions();58 void createActions();
58 void dragMoveEvent(QDragMoveEvent * event);59 void dragMoveEvent(QDragMoveEvent * event);
@@ -89,6 +90,7 @@
8990
90 // Send to Auto-DJ Action91 // Send to Auto-DJ Action
91 QAction *m_pAutoDJAct;92 QAction *m_pAutoDJAct;
93 QAction *m_pAutoDJTopAct;
9294
93 // Remove from table95 // Remove from table
94 QAction *m_pRemoveAct;96 QAction *m_pRemoveAct;