Revision 9fa2835a
app/app.iml | ||
---|---|---|
27 | 27 |
</configuration> |
28 | 28 |
</facet> |
29 | 29 |
</component> |
30 |
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
|
30 |
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7"> |
|
31 | 31 |
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" /> |
32 | 32 |
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" /> |
33 | 33 |
<exclude-output /> |
34 | 34 |
<content url="file://$MODULE_DIR$"> |
35 | 35 |
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" /> |
36 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" /> |
|
36 | 37 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" /> |
37 | 38 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" /> |
38 | 39 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" /> |
39 | 40 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" /> |
40 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" /> |
|
41 | 41 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" /> |
42 | 42 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" /> |
43 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" /> |
|
43 | 44 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" /> |
44 | 45 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" /> |
45 | 46 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" /> |
46 | 47 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" /> |
47 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" /> |
|
48 | 48 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" /> |
49 | 49 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" /> |
50 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" /> |
|
50 | 51 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" /> |
51 | 52 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" /> |
52 | 53 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" /> |
... | ... | |
55 | 56 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" /> |
56 | 57 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" /> |
57 | 58 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" /> |
59 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/res" type="java-test-resource" /> |
|
60 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/resources" type="java-test-resource" /> |
|
61 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/assets" type="java-test-resource" /> |
|
62 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/aidl" isTestSource="true" /> |
|
63 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/java" isTestSource="true" /> |
|
64 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/jni" isTestSource="true" /> |
|
65 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/rs" isTestSource="true" /> |
|
66 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/shaders" isTestSource="true" /> |
|
58 | 67 |
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" /> |
59 | 68 |
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" /> |
60 | 69 |
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" /> |
... | ... | |
89 | 98 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" /> |
90 | 99 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" /> |
91 | 100 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" /> |
101 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-manifest" /> |
|
92 | 102 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" /> |
103 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes-jar" /> |
|
93 | 104 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> |
94 | 105 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" /> |
95 | 106 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" /> |
... | ... | |
97 | 108 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" /> |
98 | 109 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-resources" /> |
99 | 110 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" /> |
111 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaPrecompile" /> |
|
100 | 112 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" /> |
113 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" /> |
|
101 | 114 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" /> |
102 | 115 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndkBuild" /> |
103 | 116 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" /> |
117 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" /> |
|
104 | 118 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" /> |
105 | 119 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> |
106 | 120 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" /> |
107 | 121 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" /> |
108 | 122 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" /> |
109 | 123 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" /> |
124 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/splits-support" /> |
|
110 | 125 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" /> |
126 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" /> |
|
111 | 127 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" /> |
112 | 128 |
<excludeFolder url="file://$MODULE_DIR$/build/outputs" /> |
113 | 129 |
<excludeFolder url="file://$MODULE_DIR$/build/reports" /> |
... | ... | |
115 | 131 |
</content> |
116 | 132 |
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" /> |
117 | 133 |
<orderEntry type="sourceFolder" forTests="false" /> |
118 |
<orderEntry type="library" exported="" name="transition-25.3.1" level="project" />
|
|
119 |
<orderEntry type="library" exported="" name="picasso-2.6.0-" level="project" />
|
|
120 |
<orderEntry type="library" exported="" name="design-25.3.1" level="project" />
|
|
121 |
<orderEntry type="library" exported="" name="support-core-ui-25.3.1" level="project" />
|
|
122 |
<orderEntry type="library" exported="" name="guava-20.0" level="project" />
|
|
123 |
<orderEntry type="library" exported="" name="support-v4-25.3.1" level="project" />
|
|
124 |
<orderEntry type="library" exported="" name="support-media-compat-25.3.1" level="project" />
|
|
125 |
<orderEntry type="library" exported="" name="recyclerview-v7-25.3.1" level="project" />
|
|
126 |
<orderEntry type="library" exported="" name="support-annotations-25.3.1" level="project" />
|
|
127 |
<orderEntry type="library" exported="" name="appcompat-v7-25.3.1" level="project" />
|
|
128 |
<orderEntry type="library" exported="" name="support-vector-drawable-25.3.1" level="project" />
|
|
129 |
<orderEntry type="library" exported="" name="FFmpegAndroid-0.3.2" level="project" />
|
|
130 |
<orderEntry type="library" exported="" name="support-compat-25.3.1" level="project" />
|
|
131 |
<orderEntry type="library" exported="" name="support-core-utils-25.3.1" level="project" />
|
|
132 |
<orderEntry type="library" exported="" name="support-fragment-25.3.1" level="project" />
|
|
133 |
<orderEntry type="library" exported="" name="animated-vector-drawable-25.3.1" level="project" />
|
|
134 |
<orderEntry type="library" exported="" name="commons-codec-1.9" level="project" />
|
|
134 |
<orderEntry type="library" name="com.android.support:animated-vector-drawable-25.3.1" level="project" />
|
|
135 |
<orderEntry type="library" name="com.android.support:transition-25.3.1" level="project" />
|
|
136 |
<orderEntry type="library" name="com.android.support:design-25.3.1" level="project" />
|
|
137 |
<orderEntry type="library" name="com.writingminds:FFmpegAndroid-0.3.2" level="project" />
|
|
138 |
<orderEntry type="library" name="com.android.support:support-core-ui-25.3.1" level="project" />
|
|
139 |
<orderEntry type="library" name="com.android.support:appcompat-v7-25.3.1" level="project" />
|
|
140 |
<orderEntry type="library" name="com.android.support:support-compat-25.3.1" level="project" />
|
|
141 |
<orderEntry type="library" name="commons-codec:commons-codec:1.9@jar" level="project" />
|
|
142 |
<orderEntry type="library" name="com.google.guava:guava:20.0@jar" level="project" />
|
|
143 |
<orderEntry type="library" name="picasso-2.6.0:@aar" level="project" />
|
|
144 |
<orderEntry type="library" name="com.android.support:support-core-utils-25.3.1" level="project" />
|
|
145 |
<orderEntry type="library" name="com.android.support:support-vector-drawable-25.3.1" level="project" />
|
|
146 |
<orderEntry type="library" name="com.android.support:support-v4-25.3.1" level="project" />
|
|
147 |
<orderEntry type="library" name="com.android.support:support-fragment-25.3.1" level="project" />
|
|
148 |
<orderEntry type="library" name="com.android.support:recyclerview-v7-25.3.1" level="project" />
|
|
149 |
<orderEntry type="library" name="com.android.support:support-annotations:25.3.1@jar" level="project" />
|
|
150 |
<orderEntry type="library" name="com.android.support:support-media-compat-25.3.1" level="project" />
|
|
135 | 151 |
</component> |
136 | 152 |
</module> |
app/src/main/java/net/londatiga/android/ActionItem.java | ||
---|---|---|
1 |
package net.londatiga.android; |
|
2 |
|
|
3 |
import android.graphics.drawable.Drawable; |
|
4 |
import android.graphics.Bitmap; |
|
5 |
|
|
6 |
/** |
|
7 |
* Action item, displayed as menu with icon and text. |
|
8 |
* |
|
9 |
* @author Lorensius. W. L. T <lorenz@londatiga.net> |
|
10 |
* |
|
11 |
* Contributors: |
|
12 |
* - Kevin Peck <kevinwpeck@gmail.com> |
|
13 |
* |
|
14 |
*/ |
|
15 |
public class ActionItem { |
|
16 |
private Drawable icon; |
|
17 |
private Bitmap thumb; |
|
18 |
private String title; |
|
19 |
private int actionId = -1; |
|
20 |
private boolean selected; |
|
21 |
private boolean sticky; |
|
22 |
|
|
23 |
/** |
|
24 |
* Constructor |
|
25 |
* |
|
26 |
* @param actionId Action id for case statements |
|
27 |
* @param title Title |
|
28 |
* @param icon Icon to use |
|
29 |
*/ |
|
30 |
public ActionItem(int actionId, String title, Drawable icon) { |
|
31 |
this.title = title; |
|
32 |
this.icon = icon; |
|
33 |
this.actionId = actionId; |
|
34 |
} |
|
35 |
|
|
36 |
/** |
|
37 |
* Constructor |
|
38 |
*/ |
|
39 |
public ActionItem() { |
|
40 |
this(-1, null, null); |
|
41 |
} |
|
42 |
|
|
43 |
/** |
|
44 |
* Constructor |
|
45 |
* |
|
46 |
* @param actionId Action id of the item |
|
47 |
* @param title Text to show for the item |
|
48 |
*/ |
|
49 |
public ActionItem(int actionId, String title) { |
|
50 |
this(actionId, title, null); |
|
51 |
} |
|
52 |
|
|
53 |
/** |
|
54 |
* Constructor |
|
55 |
* |
|
56 |
* @param icon {@link Drawable} action icon |
|
57 |
*/ |
|
58 |
public ActionItem(Drawable icon) { |
|
59 |
this(-1, null, icon); |
|
60 |
} |
|
61 |
|
|
62 |
/** |
|
63 |
* Constructor |
|
64 |
* |
|
65 |
* @param actionId Action ID of item |
|
66 |
* @param icon {@link Drawable} action icon |
|
67 |
*/ |
|
68 |
public ActionItem(int actionId, Drawable icon) { |
|
69 |
this(actionId, null, icon); |
|
70 |
} |
|
71 |
|
|
72 |
/** |
|
73 |
* Set action title |
|
74 |
* |
|
75 |
* @param title action title |
|
76 |
*/ |
|
77 |
public void setTitle(String title) { |
|
78 |
this.title = title; |
|
79 |
} |
|
80 |
|
|
81 |
/** |
|
82 |
* Get action title |
|
83 |
* |
|
84 |
* @return action title |
|
85 |
*/ |
|
86 |
public String getTitle() { |
|
87 |
return this.title; |
|
88 |
} |
|
89 |
|
|
90 |
/** |
|
91 |
* Set action icon |
|
92 |
* |
|
93 |
* @param icon {@link Drawable} action icon |
|
94 |
*/ |
|
95 |
public void setIcon(Drawable icon) { |
|
96 |
this.icon = icon; |
|
97 |
} |
|
98 |
|
|
99 |
/** |
|
100 |
* Get action icon |
|
101 |
* @return {@link Drawable} action icon |
|
102 |
*/ |
|
103 |
public Drawable getIcon() { |
|
104 |
return this.icon; |
|
105 |
} |
|
106 |
|
|
107 |
/** |
|
108 |
* Set action id |
|
109 |
* |
|
110 |
* @param actionId Action id for this action |
|
111 |
*/ |
|
112 |
public void setActionId(int actionId) { |
|
113 |
this.actionId = actionId; |
|
114 |
} |
|
115 |
|
|
116 |
/** |
|
117 |
* @return Our action id |
|
118 |
*/ |
|
119 |
public int getActionId() { |
|
120 |
return actionId; |
|
121 |
} |
|
122 |
|
|
123 |
/** |
|
124 |
* Set sticky status of button |
|
125 |
* |
|
126 |
* @param sticky true for sticky, pop up sends event but does not disappear |
|
127 |
*/ |
|
128 |
public void setSticky(boolean sticky) { |
|
129 |
this.sticky = sticky; |
|
130 |
} |
|
131 |
|
|
132 |
/** |
|
133 |
* @return true if button is sticky, menu stays visible after press |
|
134 |
*/ |
|
135 |
public boolean isSticky() { |
|
136 |
return sticky; |
|
137 |
} |
|
138 |
|
|
139 |
/** |
|
140 |
* Set selected flag; |
|
141 |
* |
|
142 |
* @param selected Flag to indicate the item is selected |
|
143 |
*/ |
|
144 |
public void setSelected(boolean selected) { |
|
145 |
this.selected = selected; |
|
146 |
} |
|
147 |
|
|
148 |
/** |
|
149 |
* Check if item is selected |
|
150 |
* |
|
151 |
* @return true or false |
|
152 |
*/ |
|
153 |
public boolean isSelected() { |
|
154 |
return this.selected; |
|
155 |
} |
|
156 |
|
|
157 |
/** |
|
158 |
* Set thumb |
|
159 |
* |
|
160 |
* @param thumb Thumb image |
|
161 |
*/ |
|
162 |
public void setThumb(Bitmap thumb) { |
|
163 |
this.thumb = thumb; |
|
164 |
} |
|
165 |
|
|
166 |
/** |
|
167 |
* Get thumb image |
|
168 |
* |
|
169 |
* @return Thumb image |
|
170 |
*/ |
|
171 |
public Bitmap getThumb() { |
|
172 |
return this.thumb; |
|
173 |
} |
|
174 |
} |
app/src/main/java/net/londatiga/android/PopupWindows.java | ||
---|---|---|
1 |
package net.londatiga.android; |
|
2 |
|
|
3 |
import android.graphics.drawable.BitmapDrawable; |
|
4 |
import android.graphics.drawable.Drawable; |
|
5 |
|
|
6 |
import android.view.LayoutInflater; |
|
7 |
import android.view.MotionEvent; |
|
8 |
import android.view.View; |
|
9 |
import android.view.WindowManager; |
|
10 |
import android.view.View.OnTouchListener; |
|
11 |
|
|
12 |
import android.widget.PopupWindow; |
|
13 |
import android.content.Context; |
|
14 |
|
|
15 |
/** |
|
16 |
* Custom popup window. |
|
17 |
* |
|
18 |
* @author Lorensius W. L. T <lorenz@londatiga.net> |
|
19 |
* |
|
20 |
*/ |
|
21 |
public class PopupWindows { |
|
22 |
protected Context mContext; |
|
23 |
protected PopupWindow mWindow; |
|
24 |
protected View mRootView; |
|
25 |
protected Drawable mBackground = null; |
|
26 |
protected WindowManager mWindowManager; |
|
27 |
|
|
28 |
/** |
|
29 |
* Constructor. |
|
30 |
* |
|
31 |
* @param context Context |
|
32 |
*/ |
|
33 |
public PopupWindows(Context context) { |
|
34 |
mContext = context; |
|
35 |
mWindow = new PopupWindow(context); |
|
36 |
|
|
37 |
mWindow.setTouchInterceptor(new OnTouchListener() { |
|
38 |
@Override |
|
39 |
public boolean onTouch(View v, MotionEvent event) { |
|
40 |
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { |
|
41 |
mWindow.dismiss(); |
|
42 |
|
|
43 |
return true; |
|
44 |
} |
|
45 |
|
|
46 |
return false; |
|
47 |
} |
|
48 |
}); |
|
49 |
|
|
50 |
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); |
|
51 |
} |
|
52 |
|
|
53 |
/** |
|
54 |
* On dismiss |
|
55 |
*/ |
|
56 |
protected void onDismiss() { |
|
57 |
} |
|
58 |
|
|
59 |
/** |
|
60 |
* On show |
|
61 |
*/ |
|
62 |
protected void onShow() { |
|
63 |
} |
|
64 |
|
|
65 |
/** |
|
66 |
* On pre show |
|
67 |
*/ |
|
68 |
protected void preShow() { |
|
69 |
if (mRootView == null) |
|
70 |
throw new IllegalStateException("setContentView was not called with a view to display."); |
|
71 |
|
|
72 |
onShow(); |
|
73 |
|
|
74 |
if (mBackground == null) |
|
75 |
mWindow.setBackgroundDrawable(new BitmapDrawable()); |
|
76 |
else |
|
77 |
mWindow.setBackgroundDrawable(mBackground); |
|
78 |
|
|
79 |
mWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT); |
|
80 |
mWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); |
|
81 |
mWindow.setTouchable(true); |
|
82 |
mWindow.setFocusable(true); |
|
83 |
mWindow.setOutsideTouchable(true); |
|
84 |
|
|
85 |
mWindow.setContentView(mRootView); |
|
86 |
} |
|
87 |
|
|
88 |
/** |
|
89 |
* Set background drawable. |
|
90 |
* |
|
91 |
* @param background Background drawable |
|
92 |
*/ |
|
93 |
public void setBackgroundDrawable(Drawable background) { |
|
94 |
mBackground = background; |
|
95 |
} |
|
96 |
|
|
97 |
/** |
|
98 |
* Set content view. |
|
99 |
* |
|
100 |
* @param root Root view |
|
101 |
*/ |
|
102 |
public void setContentView(View root) { |
|
103 |
mRootView = root; |
|
104 |
|
|
105 |
mWindow.setContentView(root); |
|
106 |
} |
|
107 |
|
|
108 |
/** |
|
109 |
* Set content view. |
|
110 |
* |
|
111 |
* @param layoutResID Resource id |
|
112 |
*/ |
|
113 |
public void setContentView(int layoutResID) { |
|
114 |
LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
|
115 |
|
|
116 |
setContentView(inflator.inflate(layoutResID, null)); |
|
117 |
} |
|
118 |
|
|
119 |
/** |
|
120 |
* Set listener on window dismissed. |
|
121 |
* |
|
122 |
* @param listener |
|
123 |
*/ |
|
124 |
public void setOnDismissListener(PopupWindow.OnDismissListener listener) { |
|
125 |
mWindow.setOnDismissListener(listener); |
|
126 |
} |
|
127 |
|
|
128 |
/** |
|
129 |
* Dismiss the popup window. |
|
130 |
*/ |
|
131 |
public void dismiss() { |
|
132 |
mWindow.dismiss(); |
|
133 |
} |
|
134 |
} |
app/src/main/java/net/londatiga/android/QuickAction.java | ||
---|---|---|
1 |
package net.londatiga.android; |
|
2 |
|
|
3 |
import java.util.ArrayList; |
|
4 |
import java.util.List; |
|
5 |
|
|
6 |
import org.witness.sscphase1.R; |
|
7 |
|
|
8 |
import android.content.Context; |
|
9 |
import android.graphics.Rect; |
|
10 |
import android.graphics.drawable.Drawable; |
|
11 |
import android.view.Gravity; |
|
12 |
import android.view.LayoutInflater; |
|
13 |
import android.view.View; |
|
14 |
import android.view.View.OnClickListener; |
|
15 |
import android.view.ViewGroup; |
|
16 |
import android.view.ViewGroup.LayoutParams; |
|
17 |
import android.view.animation.Animation; |
|
18 |
import android.view.animation.AnimationUtils; |
|
19 |
import android.view.animation.Interpolator; |
|
20 |
import android.widget.ImageView; |
|
21 |
import android.widget.PopupWindow.OnDismissListener; |
|
22 |
import android.widget.TextView; |
|
23 |
|
|
24 |
/** |
|
25 |
* QuickAction dialog. |
|
26 |
* |
|
27 |
* @author Lorensius W. L. T <lorenz@londatiga.net> |
|
28 |
* |
|
29 |
* Contributors: |
|
30 |
* - Kevin Peck <kevinwpeck@gmail.com> |
|
31 |
*/ |
|
32 |
public class QuickAction extends PopupWindows implements OnDismissListener { |
|
33 |
private ImageView mArrowUp; |
|
34 |
private ImageView mArrowDown; |
|
35 |
private Animation mTrackAnim; |
|
36 |
private LayoutInflater inflater; |
|
37 |
private ViewGroup mTrack; |
|
38 |
private OnActionItemClickListener mItemClickListener; |
|
39 |
private OnDismissListener mDismissListener; |
|
40 |
|
|
41 |
private List<ActionItem> mActionItemList = new ArrayList<ActionItem>(); |
|
42 |
|
|
43 |
private boolean mDidAction; |
|
44 |
private boolean mAnimateTrack; |
|
45 |
|
|
46 |
private int mChildPos; |
|
47 |
private int mAnimStyle; |
|
48 |
|
|
49 |
public static final int ANIM_GROW_FROM_LEFT = 1; |
|
50 |
public static final int ANIM_GROW_FROM_RIGHT = 2; |
|
51 |
public static final int ANIM_GROW_FROM_CENTER = 3; |
|
52 |
public static final int ANIM_AUTO = 4; |
|
53 |
|
|
54 |
/** |
|
55 |
* Constructor. |
|
56 |
* |
|
57 |
* @param context Context |
|
58 |
*/ |
|
59 |
public QuickAction(Context context) { |
|
60 |
super(context); |
|
61 |
|
|
62 |
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
|
63 |
|
|
64 |
mTrackAnim = AnimationUtils.loadAnimation(context, R.anim.rail); |
|
65 |
|
|
66 |
mTrackAnim.setInterpolator(new Interpolator() { |
|
67 |
public float getInterpolation(float t) { |
|
68 |
// Pushes past the target area, then snaps back into place. |
|
69 |
// Equation for graphing: 1.2-((x*1.6)-1.1)^2 |
|
70 |
final float inner = (t * 1.55f) - 1.1f; |
|
71 |
|
|
72 |
return 1.2f - inner * inner; |
|
73 |
} |
|
74 |
}); |
|
75 |
|
|
76 |
setRootViewId(R.layout.quickaction); |
|
77 |
|
|
78 |
mAnimStyle = ANIM_AUTO; |
|
79 |
mAnimateTrack = true; |
|
80 |
mChildPos = 0; |
|
81 |
} |
|
82 |
|
|
83 |
/** |
|
84 |
* Get action item at an index |
|
85 |
* |
|
86 |
* @param index Index of item (position from callback) |
|
87 |
* |
|
88 |
* @return Action Item at the position |
|
89 |
*/ |
|
90 |
public ActionItem getActionItem(int index) { |
|
91 |
return mActionItemList.get(index); |
|
92 |
} |
|
93 |
|
|
94 |
/** |
|
95 |
* Set root view. |
|
96 |
* |
|
97 |
* @param id Layout resource id |
|
98 |
*/ |
|
99 |
public void setRootViewId(int id) { |
|
100 |
mRootView = (ViewGroup) inflater.inflate(id, null); |
|
101 |
mTrack = (ViewGroup) mRootView.findViewById(R.id.tracks); |
|
102 |
|
|
103 |
mArrowDown = (ImageView) mRootView.findViewById(R.id.arrow_down); |
|
104 |
mArrowUp = (ImageView) mRootView.findViewById(R.id.arrow_up); |
|
105 |
|
|
106 |
//This was previously defined on show() method, moved here to prevent force close that occured |
|
107 |
//when tapping fastly on a view to show quickaction dialog. |
|
108 |
//Thanx to zammbi (github.com/zammbi) |
|
109 |
mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); |
|
110 |
|
|
111 |
setContentView(mRootView); |
|
112 |
} |
|
113 |
|
|
114 |
/** |
|
115 |
* Animate track. |
|
116 |
* |
|
117 |
* @param mAnimateTrack flag to animate track |
|
118 |
*/ |
|
119 |
public void mAnimateTrack(boolean mAnimateTrack) { |
|
120 |
this.mAnimateTrack = mAnimateTrack; |
|
121 |
} |
|
122 |
|
|
123 |
/** |
|
124 |
* Set animation style. |
|
125 |
* |
|
126 |
* @param mAnimStyle animation style, default is set to ANIM_AUTO |
|
127 |
*/ |
|
128 |
public void setAnimStyle(int mAnimStyle) { |
|
129 |
this.mAnimStyle = mAnimStyle; |
|
130 |
} |
|
131 |
|
|
132 |
/** |
|
133 |
* Add action item |
|
134 |
* |
|
135 |
* @param action {@link ActionItem} |
|
136 |
*/ |
|
137 |
public void addActionItem(ActionItem action) { |
|
138 |
mActionItemList.add(action); |
|
139 |
|
|
140 |
String title = action.getTitle(); |
|
141 |
Drawable icon = action.getIcon(); |
|
142 |
|
|
143 |
View container = (View) inflater.inflate(R.layout.action_item, null); |
|
144 |
|
|
145 |
ImageView img = (ImageView) container.findViewById(R.id.iv_icon); |
|
146 |
TextView text = (TextView) container.findViewById(R.id.tv_title); |
|
147 |
|
|
148 |
if (icon != null) { |
|
149 |
img.setImageDrawable(icon); |
|
150 |
} else { |
|
151 |
img.setVisibility(View.GONE); |
|
152 |
} |
|
153 |
|
|
154 |
if (title != null) { |
|
155 |
text.setText(title); |
|
156 |
} else { |
|
157 |
text.setVisibility(View.GONE); |
|
158 |
} |
|
159 |
|
|
160 |
final int pos = mChildPos; |
|
161 |
final int actionId = action.getActionId(); |
|
162 |
|
|
163 |
container.setOnClickListener(new OnClickListener() { |
|
164 |
@Override |
|
165 |
public void onClick(View v) { |
|
166 |
if (mItemClickListener != null) { |
|
167 |
mItemClickListener.onItemClick(QuickAction.this, pos, actionId); |
|
168 |
} |
|
169 |
|
|
170 |
if (!getActionItem(pos).isSticky()) { |
|
171 |
mDidAction = true; |
|
172 |
|
|
173 |
//workaround for transparent background bug |
|
174 |
//thx to Roman Wozniak <roman.wozniak@gmail.com> |
|
175 |
v.post(new Runnable() { |
|
176 |
@Override |
|
177 |
public void run() { |
|
178 |
dismiss(); |
|
179 |
} |
|
180 |
}); |
|
181 |
} |
|
182 |
} |
|
183 |
}); |
|
184 |
|
|
185 |
container.setFocusable(true); |
|
186 |
container.setClickable(true); |
|
187 |
|
|
188 |
mTrack.addView(container, mChildPos+1); |
|
189 |
|
|
190 |
mChildPos++; |
|
191 |
} |
|
192 |
|
|
193 |
public void setOnActionItemClickListener(OnActionItemClickListener listener) { |
|
194 |
mItemClickListener = listener; |
|
195 |
} |
|
196 |
|
|
197 |
/** |
|
198 |
* Show popup mWindow |
|
199 |
*/ |
|
200 |
public void show (View anchor, int locX, int locY) { |
|
201 |
preShow(); |
|
202 |
|
|
203 |
//int[] location = new int[2]; |
|
204 |
|
|
205 |
|
|
206 |
mDidAction = false; |
|
207 |
|
|
208 |
// anchor.getLocationOnScreen(location); |
|
209 |
|
|
210 |
Rect anchorRect = new Rect(locX, locY, locX + anchor.getWidth(), locY |
|
211 |
+ anchor.getHeight()); |
|
212 |
|
|
213 |
//mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); |
|
214 |
mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); |
|
215 |
|
|
216 |
int rootWidth = mRootView.getMeasuredWidth(); |
|
217 |
int rootHeight = mRootView.getMeasuredHeight(); |
|
218 |
|
|
219 |
int screenWidth = mWindowManager.getDefaultDisplay().getWidth(); |
|
220 |
//int screenHeight = mWindowManager.getDefaultDisplay().getHeight(); |
|
221 |
|
|
222 |
int xPos = (screenWidth - rootWidth) / 2; |
|
223 |
int yPos = anchorRect.top - rootHeight; |
|
224 |
|
|
225 |
boolean onTop = true; |
|
226 |
|
|
227 |
// display on bottom |
|
228 |
if (rootHeight > anchor.getTop()) { |
|
229 |
yPos = anchorRect.bottom; |
|
230 |
onTop = false; |
|
231 |
} |
|
232 |
|
|
233 |
showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), anchorRect.centerX()); |
|
234 |
|
|
235 |
setAnimationStyle(screenWidth, anchorRect.centerX(), onTop); |
|
236 |
|
|
237 |
mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos); |
|
238 |
|
|
239 |
if (mAnimateTrack) mTrack.startAnimation(mTrackAnim); |
|
240 |
} |
|
241 |
|
|
242 |
/** |
|
243 |
* Set animation style |
|
244 |
* |
|
245 |
* @param screenWidth Screen width |
|
246 |
* @param requestedX distance from left screen |
|
247 |
* @param onTop flag to indicate where the popup should be displayed. Set TRUE if displayed on top of anchor and vice versa |
|
248 |
*/ |
|
249 |
private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) { |
|
250 |
int arrowPos = requestedX - mArrowUp.getMeasuredWidth()/2; |
|
251 |
|
|
252 |
switch (mAnimStyle) { |
|
253 |
case ANIM_GROW_FROM_LEFT: |
|
254 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left); |
|
255 |
break; |
|
256 |
|
|
257 |
case ANIM_GROW_FROM_RIGHT: |
|
258 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right); |
|
259 |
break; |
|
260 |
|
|
261 |
case ANIM_GROW_FROM_CENTER: |
|
262 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center); |
|
263 |
break; |
|
264 |
|
|
265 |
case ANIM_AUTO: |
|
266 |
if (arrowPos <= screenWidth/4) { |
|
267 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left); |
|
268 |
} else if (arrowPos > screenWidth/4 && arrowPos < 3 * (screenWidth/4)) { |
|
269 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center); |
|
270 |
} else { |
|
271 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopDownMenu_Right : R.style.Animations_PopDownMenu_Right); |
|
272 |
} |
|
273 |
|
|
274 |
break; |
|
275 |
} |
|
276 |
} |
|
277 |
|
|
278 |
/** |
|
279 |
* Show arrow |
|
280 |
* |
|
281 |
* @param whichArrow arrow type resource id |
|
282 |
* @param requestedX distance from left screen |
|
283 |
*/ |
|
284 |
private void showArrow(int whichArrow, int requestedX) { |
|
285 |
final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown; |
|
286 |
final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp; |
|
287 |
|
|
288 |
final int arrowWidth = mArrowUp.getMeasuredWidth(); |
|
289 |
|
|
290 |
showArrow.setVisibility(View.VISIBLE); |
|
291 |
|
|
292 |
ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams(); |
|
293 |
|
|
294 |
param.leftMargin = requestedX - arrowWidth / 2; |
|
295 |
|
|
296 |
hideArrow.setVisibility(View.INVISIBLE); |
|
297 |
} |
|
298 |
|
|
299 |
/** |
|
300 |
* Set listener for window dismissed. This listener will only be fired if the quicakction dialog is dismissed |
|
301 |
* by clicking outside the dialog or clicking on sticky item. |
|
302 |
*/ |
|
303 |
public void setOnDismissListener(QuickAction.OnDismissListener listener) { |
|
304 |
setOnDismissListener(this); |
|
305 |
|
|
306 |
mDismissListener = listener; |
|
307 |
} |
|
308 |
|
|
309 |
@Override |
|
310 |
public void onDismiss() { |
|
311 |
if (!mDidAction && mDismissListener != null) { |
|
312 |
mDismissListener.onDismiss(); |
|
313 |
} |
|
314 |
} |
|
315 |
|
|
316 |
/** |
|
317 |
* Listener for item click |
|
318 |
* |
|
319 |
*/ |
|
320 |
public interface OnActionItemClickListener { |
|
321 |
public abstract void onItemClick(QuickAction source, int pos, int actionId); |
|
322 |
} |
|
323 |
|
|
324 |
/** |
|
325 |
* Listener for window dismiss |
|
326 |
* |
|
327 |
*/ |
|
328 |
public interface OnDismissListener { |
|
329 |
public abstract void onDismiss(); |
|
330 |
} |
|
331 |
} |
app/src/main/java/org/witness/ssc/video/FFMPEGWrapper.java | ||
---|---|---|
20 | 20 |
public class FFMPEGWrapper { |
21 | 21 |
|
22 | 22 |
Context context; |
23 |
FFmpeg ffmpeg; |
|
23 | 24 |
|
24 | 25 |
public FFMPEGWrapper(Context _context) throws FileNotFoundException, IOException { |
25 | 26 |
context = _context; |
26 | 27 |
|
27 |
FFmpeg ffmpeg = FFmpeg.getInstance(context); |
|
28 |
try { |
|
28 |
ffmpeg = FFmpeg.getInstance(context); |
|
29 |
|
|
30 |
try { |
|
29 | 31 |
ffmpeg.loadBinary(new LoadBinaryResponseHandler() { |
30 | 32 |
|
31 | 33 |
@Override |
... | ... | |
54 | 56 |
|
55 | 57 |
|
56 | 58 |
public void processVideo( |
57 |
ArrayList<RegionTrail> regionTrails, File inputFile, File outputFile, int frameRate, int mDuration, int mOutputLength,
|
|
59 |
ArrayList<RegionTrail> regionTrails, File inputFile, File outputFile, int frameRate, float startTime, float duration,
|
|
58 | 60 |
boolean compressVideo, int obscureVideoAmount, int obscureAudioAmount, ExecuteBinaryResponseHandler listener) throws Exception { |
59 | 61 |
|
60 | 62 |
DecimalFormat df = new DecimalFormat("####0.00"); |
... | ... | |
65 | 67 |
alCmds.add("-i"); |
66 | 68 |
alCmds.add(inputFile.getCanonicalPath()); |
67 | 69 |
|
68 |
if (mOutputLength > 0)
|
|
70 |
if (duration > 0)
|
|
69 | 71 |
{ |
72 |
alCmds.add("-ss"); |
|
73 |
alCmds.add(df.format(startTime)); |
|
74 |
|
|
70 | 75 |
alCmds.add("-t"); |
71 |
alCmds.add(mOutputLength+"");
|
|
76 |
alCmds.add(df.format(duration));
|
|
72 | 77 |
} |
73 | 78 |
|
74 | 79 |
if (frameRate > 0) |
... | ... | |
119 | 124 |
if (trail.isDoTweening() && trail.getRegionCount() > 1) { |
120 | 125 |
int timeInc = 100; |
121 | 126 |
|
122 |
for (int i = 0; i < mDuration; i = i + timeInc) {
|
|
127 |
for (int i = 0; i < ((int)duration); i = i + timeInc) {
|
|
123 | 128 |
ObscureRegion or = trail.getCurrentRegion(i, trail.isDoTweening()); |
124 | 129 |
if (or != null) { |
125 | 130 |
|
... | ... | |
131 | 136 |
float timeStart = ((float) or.timeStamp) / 1000f; |
132 | 137 |
float timeStop = (((float) or.timeStamp) + 100) / 1000f; |
133 | 138 |
|
134 |
float timeEnd = ((float) mDuration) / 1000f;
|
|
139 |
float timeEnd = duration / 1000f;
|
|
135 | 140 |
timeStop = Math.max(timeStop, timeEnd); |
136 | 141 |
|
137 | 142 |
filters.append("drawbox=x=" + x + ":y=" + y |
... | ... | |
184 | 189 |
try { |
185 | 190 |
|
186 | 191 |
|
187 |
FFmpeg ffmpeg = FFmpeg.getInstance(context); |
|
188 | 192 |
// to execute "ffmpeg -version" command you just need to pass "-version" |
189 | 193 |
ffmpeg.execute(cmd,listener); |
190 | 194 |
} catch (FFmpegCommandAlreadyRunningException e) { |
... | ... | |
251 | 255 |
|
252 | 256 |
|
253 | 257 |
} |
254 |
|
|
258 |
|
|
259 |
public FFmpeg getFFMPEG () |
|
260 |
{ |
|
261 |
return ffmpeg; |
|
262 |
} |
|
255 | 263 |
|
256 | 264 |
} |
257 | 265 |
|
app/src/main/java/org/witness/ssc/video/VideoEditor.java | ||
---|---|---|
64 | 64 |
import android.widget.ImageButton; |
65 | 65 |
import android.widget.ImageView; |
66 | 66 |
import android.widget.MediaController; |
67 |
import android.widget.ProgressBar; |
|
67 | 68 |
import android.widget.SeekBar; |
68 | 69 |
import android.widget.Toast; |
69 | 70 |
import android.widget.VideoView; |
70 | 71 |
|
71 | 72 |
import com.github.hiteshsondhi88.libffmpeg.ExecuteBinaryResponseHandler; |
72 | 73 |
|
73 |
import net.londatiga.android.ActionItem; |
|
74 |
import net.londatiga.android.QuickAction; |
|
75 |
import net.londatiga.android.QuickAction.OnActionItemClickListener; |
|
76 | 74 |
|
77 | 75 |
import org.witness.securesmartcam.detect.AndroidFaceDetection; |
78 | 76 |
import org.witness.securesmartcam.detect.DetectedFace; |
... | ... | |
96 | 94 |
OnBufferingUpdateListener, OnPreparedListener, OnSeekCompleteListener, |
97 | 95 |
OnVideoSizeChangedListener, SurfaceHolder.Callback, |
98 | 96 |
MediaController.MediaPlayerControl, OnTouchListener, |
99 |
InOutPlayheadSeekBarChangeListener, OnActionItemClickListener {
|
|
97 |
InOutPlayheadSeekBarChangeListener { |
|
100 | 98 |
|
101 | 99 |
public static final String LOGTAG = ObscuraApp.TAG; |
102 | 100 |
|
... | ... | |
111 | 109 |
|
112 | 110 |
private final static int HUMAN_OFFSET_BUFFER = 50; |
113 | 111 |
|
114 |
ProgressDialog progressDialog; |
|
115 | 112 |
int completeActionFlag = 3; |
116 | 113 |
|
117 | 114 |
Uri originalVideoUri; |
... | ... | |
140 | 137 |
|
141 | 138 |
Bitmap bitmapPixel; |
142 | 139 |
|
143 |
InOutPlayheadSeekBar progressBar;
|
|
140 |
InOutPlayheadSeekBar mVideoSeekbar;
|
|
144 | 141 |
//RegionBarArea regionBarArea; |
145 | 142 |
|
146 | 143 |
int videoWidth = 0; |
... | ... | |
181 | 178 |
private final static String DEFAULT_OUT_WIDTH = "480"; |
182 | 179 |
private final static String DEFAULT_OUT_HEIGHT = "320"; |
183 | 180 |
|
181 |
private ProgressBar mProgressBar; |
|
184 | 182 |
|
185 | 183 |
private Handler mHandler = new Handler() { |
186 | 184 |
public void handleMessage(Message msg) { |
... | ... | |
201 | 199 |
Date dateProgress = sdf.parse(time); |
202 | 200 |
long progress = dateProgress.getSeconds()*1000; |
203 | 201 |
int percentComplete = (int)((((float)progress)/((float)mDuration))*100f); |
204 |
progressDialog.setProgress(percentComplete);
|
|
202 |
mProgressBar.setProgress(percentComplete);
|
|
205 | 203 |
} |
206 | 204 |
} |
207 | 205 |
catch (Exception e) |
... | ... | |
215 | 213 |
mCancelled = true; |
216 | 214 |
mAutoDetectEnabled = false; |
217 | 215 |
killVideoProcessor(); |
218 |
|
|
216 |
mProgressBar.setVisibility(View.GONE); |
|
219 | 217 |
break; |
220 | 218 |
|
221 | 219 |
case 3: //completed |
222 |
progressDialog.dismiss(); |
|
223 | 220 |
askPostProcessAction(); |
224 | 221 |
|
222 |
mProgressBar.setVisibility(View.GONE); |
|
225 | 223 |
break; |
226 | 224 |
|
227 | 225 |
case 5: |
... | ... | |
312 | 310 |
mediaPlayer.prepare(); |
313 | 311 |
mDuration = mediaPlayer.getDuration(); |
314 | 312 |
|
315 |
progressBar.setMax(mDuration);
|
|
313 |
mVideoSeekbar.setMax(mDuration);
|
|
316 | 314 |
|
317 | 315 |
} catch (Exception e) { |
318 | 316 |
Log.v(LOGTAG, "IllegalStateException " + e.getMessage()); |
... | ... | |
375 | 373 |
mediaPlayer.prepare(); |
376 | 374 |
mDuration = mediaPlayer.getDuration(); |
377 | 375 |
|
378 |
progressBar.setMax(mDuration);
|
|
376 |
mVideoSeekbar.setMax(mDuration);
|
|
379 | 377 |
|
380 | 378 |
} catch (Exception e) { |
381 | 379 |
Log.v(LOGTAG, "IllegalStateException " + e.getMessage()); |
... | ... | |
462 | 460 |
private void beginAutoDetect() { |
463 | 461 |
mAutoDetectEnabled = true; |
464 | 462 |
|
465 |
progressDialog = new ProgressDialog(this); |
|
466 |
progressDialog = ProgressDialog.show(this, "", "Detecting faces...", true, true); |
|
467 |
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); |
|
468 |
progressDialog.setCancelable(true); |
|
469 |
Message msg = mHandler.obtainMessage(2); |
|
470 |
msg.getData().putString("status", "cancelled"); |
|
471 |
progressDialog.setCancelMessage(msg); |
|
472 |
|
|
473 |
progressDialog.show(); |
|
474 |
|
|
475 | 463 |
new Thread(doAutoDetect).start(); |
476 | 464 |
|
477 | 465 |
} |
... | ... | |
623 | 611 |
try { |
624 | 612 |
seekTo(f); |
625 | 613 |
|
626 |
progressBar.setProgress(mediaPlayer.getCurrentPosition());
|
|
614 |
mVideoSeekbar.setProgress(mediaPlayer.getCurrentPosition());
|
|
627 | 615 |
|
628 | 616 |
//Bitmap bmp = getVideoFrame(rPath,f*1000); |
629 | 617 |
|
... | ... | |
668 | 656 |
try { |
669 | 657 |
if (mediaPlayer != null && mediaPlayer.isPlaying()) { |
670 | 658 |
int curr = mediaPlayer.getCurrentPosition(); |
671 |
progressBar.setProgress(curr);
|
|
659 |
mVideoSeekbar.setProgress(curr);
|
|
672 | 660 |
updateRegionDisplay(curr); |
673 | 661 |
mHandler.post(this); |
674 | 662 |
} |
... | ... | |
835 | 823 |
|
836 | 824 |
boolean handled = false; |
837 | 825 |
|
838 |
if (v == progressBar) {
|
|
826 |
if (v == mVideoSeekbar) {
|
|
839 | 827 |
|
840 | 828 |
if (currentUri != originalVideoUri) |
841 | 829 |
{ |
... | ... | |
853 | 841 |
} |
854 | 842 |
|
855 | 843 |
|
856 |
mediaPlayer.seekTo(progressBar.getProgress());
|
|
844 |
mediaPlayer.seekTo(mVideoSeekbar.getProgress());
|
|
857 | 845 |
// Attempt to get the player to update it's view - NOT WORKING |
858 | 846 |
} |
859 | 847 |
|
... | ... | |
1042 | 1030 |
|
1043 | 1031 |
case R.id.menu_save: |
1044 | 1032 |
|
1045 |
|
|
1033 |
resetMediaPlayer(originalVideoUri); |
|
1046 | 1034 |
processVideo(false); |
1047 | 1035 |
|
1048 | 1036 |
return true; |
... | ... | |
1068 | 1056 |
|
1069 | 1057 |
PowerManager.WakeLock wl; |
1070 | 1058 |
|
1071 |
private void processVideo(boolean isPreview) { |
|
1059 |
private synchronized void processVideo(boolean isPreview) { |
|
1060 |
|
|
1061 |
if (ffmpeg != null |
|
1062 |
&& ffmpeg.getFFMPEG().isFFmpegCommandRunning()) |
|
1063 |
ffmpeg.getFFMPEG().killRunningProcesses(); |
|
1072 | 1064 |
|
1073 | 1065 |
mIsPreview = isPreview; |
1074 | 1066 |
|
1067 |
mProgressBar.setVisibility(View.VISIBLE); |
|
1068 |
mProgressBar.setProgress(0); |
|
1069 |
|
|
1075 | 1070 |
if (isPreview) |
1076 | 1071 |
{ |
1077 | 1072 |
saveFile = new File(fileExternDir,"obscuracam-preview-tmp." + outFormat); |
1078 | 1073 |
} |
1079 | 1074 |
else { |
1075 |
if (saveFile != null |
|
1076 |
&& saveFile.exists() && saveFile.getName().contains("preview")) |
|
1077 |
saveFile.delete(); |
|
1078 |
|
|
1080 | 1079 |
createCleanSavePath(outFormat); |
1080 |
|
|
1081 |
mSnackbar = Snackbar.make(findViewById(R.id.frameRoot), R.string.processing, Snackbar.LENGTH_INDEFINITE); |
|
1082 |
mSnackbar.show(); |
|
1081 | 1083 |
} |
1082 | 1084 |
|
1083 | 1085 |
mCancelled = false; |
1084 | 1086 |
|
1085 | 1087 |
mediaPlayer.pause(); |
1086 | 1088 |
|
1087 |
progressDialog = new ProgressDialog(this); |
|
1088 |
progressDialog.setMessage("Processing. Please wait..."); |
|
1089 |
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); |
|
1090 |
progressDialog.setMax(100); |
|
1091 |
progressDialog.setProgress(0); |
|
1092 |
progressDialog.setCancelable(true); |
|
1093 |
|
|
1094 |
Message msg = mHandler.obtainMessage(2); |
|
1095 |
msg.getData().putString("status", "cancelled"); |
|
1096 |
progressDialog.setCancelMessage(msg); |
|
1097 |
|
|
1098 |
progressDialog.show(); |
|
1099 |
|
|
1100 | 1089 |
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); |
1101 | 1090 |
wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag"); |
1102 | 1091 |
wl.acquire(); |
... | ... | |
1105 | 1094 |
if (ffmpeg == null) |
1106 | 1095 |
ffmpeg = new FFMPEGWrapper(VideoEditor.this.getBaseContext()); |
1107 | 1096 |
|
1108 |
int outputLength = -1; |
|
1109 | 1097 |
int frameRate = 0; |
1110 | 1098 |
|
1099 |
float startTime = ((float)mediaPlayer.getCurrentPosition())/1000f; |
|
1100 |
float duration = (float)mDuration/1000f; |
|
1101 |
|
|
1111 | 1102 |
if (isPreview) { |
1112 | 1103 |
frameRate = 1; |
1113 |
outputLength = Math.min(mDuration, 5); |
|
1114 |
mDuration = outputLength; |
|
1104 |
duration = Math.min(duration - startTime, 1f); |
|
1115 | 1105 |
} |
1106 |
|
|
1116 | 1107 |
else if (mObscureVideoAmount > 0) |
1117 | 1108 |
{ |
1118 |
frameRate = 15;
|
|
1109 |
frameRate = 3;
|
|
1119 | 1110 |
} |
1120 | 1111 |
|
1121 | 1112 |
// Could make some high/low quality presets |
1122 | 1113 |
ffmpeg.processVideo(obscureTrails, recordingFile, saveFile, |
1123 |
frameRate, mDuration, outputLength, mCompressVideo, mObscureVideoAmount, mObscureAudioAmount,
|
|
1114 |
frameRate, startTime, duration, mCompressVideo, mObscureVideoAmount, mObscureAudioAmount,
|
|
1124 | 1115 |
new ExecuteBinaryResponseHandler() { |
1125 | 1116 |
|
1126 | 1117 |
@Override |
... | ... | |
1187 | 1178 |
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(saveFile))); |
1188 | 1179 |
} |
1189 | 1180 |
|
1181 |
Snackbar mSnackbar; |
|
1182 |
|
|
1190 | 1183 |
private void askPostProcessAction() { |
1191 | 1184 |
if (saveFile != null && saveFile.exists()) { |
1192 | 1185 |
|
... | ... | |
1194 | 1187 |
start(); |
1195 | 1188 |
|
1196 | 1189 |
if (!mIsPreview) { |
1197 |
Snackbar snackbar = Snackbar.make(findViewById(R.id.frameRoot), R.string.processing_complete, Snackbar.LENGTH_LONG); |
|
1198 |
snackbar.setAction("Open", new OnClickListener() { |
|
1190 |
|
|
1191 |
if (mSnackbar != null) |
|
1192 |
{ |
|
1193 |
mSnackbar.dismiss(); |
|
1194 |
mSnackbar = null; |
|
1195 |
} |
|
1196 |
|
|
1197 |
mSnackbar = Snackbar.make(findViewById(R.id.frameRoot), R.string.processing_complete, Snackbar.LENGTH_LONG); |
|
1198 |
mSnackbar.setAction("Open", new OnClickListener() { |
|
1199 | 1199 |
@Override |
1200 | 1200 |
public void onClick(View view) { |
1201 | 1201 |
playVideoExternal(); |
1202 | 1202 |
} |
1203 | 1203 |
}); |
1204 |
snackbar.show();
|
|
1204 |
mSnackbar.show();
|
|
1205 | 1205 |
} |
1206 | 1206 |
} |
1207 | 1207 |
|
... | ... | |
1313 | 1313 |
|
1314 | 1314 |
videoView = (VideoView) this.findViewById(R.id.SurfaceView); |
1315 | 1315 |
|
1316 |
mProgressBar = (ProgressBar) this.findViewById(R.id.progress_spinner); |
|
1317 |
|
|
1316 | 1318 |
regionsView = (ImageView) this.findViewById(R.id.VideoEditorImageView); |
1317 | 1319 |
regionsView.setOnClickListener(new OnClickListener() { |
1318 | 1320 |
@Override |
... | ... | |
1320 | 1322 |
resetMediaPlayer(originalVideoUri); |
1321 | 1323 |
} |
1322 | 1324 |
}); |
1323 |
// regionsView.setOnTouchListener(this);
|
|
1325 |
regionsView.setOnTouchListener(this); |
|
1324 | 1326 |
|
1325 | 1327 |
surfaceHolder = videoView.getHolder(); |
1326 | 1328 |
|
... | ... | |
1329 | 1331 |
|
1330 | 1332 |
currentDisplay = getWindowManager().getDefaultDisplay(); |
1331 | 1333 |
|
1332 |
progressBar = (InOutPlayheadSeekBar) this.findViewById(R.id.InOutPlayheadSeekBar);
|
|
1334 |
mVideoSeekbar = (InOutPlayheadSeekBar) this.findViewById(R.id.InOutPlayheadSeekBar);
|
|
1333 | 1335 |
|
1334 |
progressBar.setIndeterminate(false);
|
|
1335 |
progressBar.setSecondaryProgress(0);
|
|
1336 |
progressBar.setProgress(0);
|
|
1337 |
progressBar.setInOutPlayheadSeekBarChangeListener(this);
|
|
1338 |
progressBar.setThumbsInactive();
|
|
1339 |
progressBar.setOnTouchListener(this);
|
|
1336 |
mVideoSeekbar.setIndeterminate(false);
|
|
1337 |
mVideoSeekbar.setSecondaryProgress(0);
|
|
1338 |
mVideoSeekbar.setProgress(0);
|
|
1339 |
mVideoSeekbar.setInOutPlayheadSeekBarChangeListener(this);
|
|
1340 |
mVideoSeekbar.setThumbsInactive();
|
|
1341 |
mVideoSeekbar.setOnTouchListener(this);
|
|
1340 | 1342 |
|
1341 | 1343 |
playPauseButton = (ImageButton) this.findViewById(R.id.PlayPauseImageButton); |
1342 | 1344 |
playPauseButton.setOnClickListener(new OnClickListener() { |
... | ... | |
1347 | 1349 |
playPauseButton.setImageDrawable(getResources().getDrawable(android.R.drawable.ic_media_play)); |
1348 | 1350 |
mAutoDetectEnabled = false; |
1349 | 1351 |
} else { |
1352 |
if (currentUri != originalVideoUri) |
|
1353 |
{ |
|
1354 |
resetMediaPlayer(originalVideoUri); |
|
1355 |
seekTo(0); |
|
1356 |
} |
|
1350 | 1357 |
start(); |
1351 | 1358 |
|
1352 | 1359 |
|
... | ... | |
1376 | 1383 |
} |
1377 | 1384 |
});**/ |
1378 | 1385 |
|
1379 |
findViewById(R.id.button_preview).setOnClickListener(new OnClickListener() { |
|
1380 |
@Override |
|
1381 |
public void onClick(View view) { |
|
1382 |
processVideo(true); |
|
1383 |
} |
|
1384 |
}); |
|
1385 |
|
|
1386 | 1386 |
((SeekBar)findViewById(R.id.seekbar_video_obscure)).setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { |
1387 | 1387 |
@Override |
1388 | 1388 |
public void onProgressChanged(SeekBar seekBar, int i, boolean b) { |
... | ... | |
1393 | 1393 |
} |
1394 | 1394 |
|
1395 | 1395 |
mObscureVideoAmount = i; |
1396 |
|
|
1396 | 1397 |
} |
1397 | 1398 |
|
1398 | 1399 |
@Override |
... | ... | |
1403 | 1404 |
@Override |
1404 | 1405 |
public void onStopTrackingTouch(SeekBar seekBar) { |
1405 | 1406 |
|
1407 |
processVideo(true); |
|
1406 | 1408 |
} |
1407 | 1409 |
}); |
1408 | 1410 |
|
... | ... | |
1420 | 1422 |
@Override |
1421 | 1423 |
public void onStopTrackingTouch(SeekBar seekBar) { |
1422 | 1424 |
|
1425 |
processVideo(true); |
|
1423 | 1426 |
} |
1424 | 1427 |
}); |
1425 | 1428 |
|
... | ... | |
1688 | 1691 |
|
1689 | 1692 |
} |
1690 | 1693 |
|
1691 |
@Override
|
|
1694 |
/**
|
|
1692 | 1695 |
public void onItemClick(QuickAction source, int pos, int actionId) { |
1693 | 1696 |
|
1694 | 1697 |
switch (actionId) { |
... | ... | |
1742 | 1745 |
updateRegionDisplay(mediaPlayer.getCurrentPosition()); |
1743 | 1746 |
|
1744 | 1747 |
} |
1745 |
|
|
1748 |
**/ |
|
1746 | 1749 |
|
1747 | 1750 |
/* |
1748 | 1751 |
* Actual deletion of original |
app/src/main/res/layout/videoeditor.xml | ||
---|---|---|
49 | 49 |
android:secondaryProgress="0" |
50 | 50 |
android:progressDrawable="@android:drawable/progress_horizontal" |
51 | 51 |
/> |
52 |
|
|
52 |
<ProgressBar |
|
53 |
android:layout_width="wrap_content" |
|
54 |
android:layout_height="match_parent" |
|
55 |
android:id="@+id/progress_spinner" |
|
56 |
android:visibility="gone" |
|
57 |
/> |
|
53 | 58 |
|
54 | 59 |
</LinearLayout> |
55 | 60 |
|
... | ... | |
58 | 63 |
android:layout_height="wrap_content" |
59 | 64 |
android:orientation="horizontal" |
60 | 65 |
> |
61 |
<!-- |
|
62 |
<Button |
|
63 |
android:id="@+id/button_auto" |
|
64 |
android:layout_width="wrap_content" |
|
65 |
android:layout_height="match_parent" |
|
66 |
android:text="Auto-Detect" |
|
67 |
/>--> |
|
68 | 66 |
|
69 | 67 |
<TextView |
70 |
android:layout_width="wrap_content"
|
|
68 |
android:layout_width="60dp"
|
|
71 | 69 |
android:layout_height="match_parent" |
72 | 70 |
android:text="Pixelize:" |
73 | 71 |
android:gravity="center_vertical|right" |
74 | 72 |
/> |
75 | 73 |
<SeekBar |
76 | 74 |
android:id="@+id/seekbar_video_obscure" |
77 |
android:layout_width="80dp"
|
|
75 |
android:layout_width="120dp"
|
|
78 | 76 |
android:layout_height="match_parent" |
79 | 77 |
android:max="128" |
80 | 78 |
|
81 | 79 |
/> |
82 | 80 |
<TextView |
83 |
android:layout_width="wrap_content"
|
|
81 |
android:layout_width="60dp"
|
|
84 | 82 |
android:layout_height="match_parent" |
85 | 83 |
android:text="Distort:" |
86 | 84 |
android:gravity="center_vertical|right" |
87 | 85 |
/> |
88 | 86 |
<SeekBar |
89 | 87 |
android:id="@+id/seekbar_audio_obscure" |
90 |
android:layout_width="80dp"
|
|
88 |
android:layout_width="120dp"
|
|
91 | 89 |
android:layout_height="match_parent" |
92 | 90 |
android:max="64" |
93 | 91 |
|
94 | 92 |
/> |
95 |
<Button |
|
96 |
android:id="@+id/button_preview" |
|
97 |
android:layout_width="wrap_content" |
|
98 |
android:layout_height="match_parent" |
|
99 |
android:text="Preview" |
|
100 |
/> |
|
93 |
|
|
94 |
|
|
95 |
</LinearLayout> |
|
96 |
<!-- |
|
97 |
<LinearLayout |
|
98 |
android:layout_width="match_parent" |
|
99 |
android:layout_height="wrap_content" |
|
100 |
android:orientation="horizontal" |
|
101 |
> |
|
102 |
|
|
103 |
<TextView |
|
104 |
android:layout_width="60dp" |
|
105 |
android:layout_height="match_parent" |
|
106 |
android:text="Brighten:" |
|
107 |
android:gravity="center_vertical|right" |
|
108 |
/> |
|
109 |
<SeekBar |
|
110 |
android:id="@+id/seekbar_video_brightness" |
|
111 |
android:layout_width="120dp" |
|
112 |
android:layout_height="match_parent" |
|
113 |
android:max="128" |
|
114 |
|
|
115 |
/> |
|
116 |
<TextView |
|
117 |
android:layout_width="60dp" |
|
118 |
android:layout_height="match_parent" |
|
119 |
android:text="Saturate:" |
|
120 |
android:gravity="center_vertical|right" |
|
121 |
/> |
|
122 |
<SeekBar |
|
123 |
android:id="@+id/seekbar_video_saturate" |
|
124 |
android:layout_width="120dp" |
|
125 |
android:layout_height="match_parent" |
|
126 |
android:max="64" |
|
127 |
|
|
128 |
/> |
|
129 |
|
|
101 | 130 |
|
102 | 131 |
</LinearLayout> |
132 |
--> |
|
103 | 133 |
</LinearLayout> |
104 | 134 |
|
105 | 135 |
|
app/src/main/res/values/strings.xml | ||
---|---|---|
142 | 142 |
<string name="video_remote_trail">Remove Trail</string> |
143 | 143 |
<string name="do_tweet">Do Tween</string> |
144 | 144 |
<string name="video_remove_keyframe">Remove Keyframe</string> |
145 |
<string name="processing">Processing...</string> |
|
145 | 146 |
|
146 | 147 |
</resources> |
app/src/main/res/values/styles.xml | ||
---|---|---|
27 | 27 |
<style name="Animations" /> |
28 | 28 |
|
29 | 29 |
<!-- PopDownMenu --> |
30 |
<!-- |
|
31 |
|
|
30 | 32 |
<style name="Animations.PopDownMenu" /> |
31 | 33 |
|
32 | 34 |
<style name="Animations.PopDownMenu.Left"> |
... | ... | |
43 | 45 |
<item name="@android:windowEnterAnimation">@anim/grow_from_top</item> |
44 | 46 |
<item name="@android:windowExitAnimation">@anim/shrink_from_bottom</item> |
45 | 47 |
</style> |
46 |
|
|
48 |
--> |
|
49 |
|
|
47 | 50 |
<!-- PopUpMenu --> |
51 |
<!-- |
|
48 | 52 |
<style name="Animations.PopUpMenu" /> |
49 | 53 |
|
50 | 54 |
<style name="Animations.PopUpMenu.Left"> |
... | ... | |
61 | 65 |
<item name="@android:windowEnterAnimation">@anim/grow_from_bottom</item> |
62 | 66 |
<item name="@android:windowExitAnimation">@anim/shrink_from_top</item> |
63 | 67 |
</style> |
64 |
|
|
68 |
--> |
|
69 |
|
|
65 | 70 |
<style name="CustomTheme"> |
66 | 71 |
<item name="android:windowNoTitle">true</item> |
67 | 72 |
<item name="android:paddingTop">10px</item> |
Also available in: Unified diff