Changeset 23193 in osm for applications/editors/josm/plugins/videomapping
- Timestamp:
- 2010-09-15T19:01:04+02:00 (14 years ago)
- Location:
- applications/editors/josm/plugins/videomapping
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/videomapping/src/org/openstreetmap/josm/plugins/videomapping/GpsPlayer.java
r23173 r23193 17 17 //for GPS play control, secure stepping through list and interpolation work in current projection 18 18 public class GpsPlayer { 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 int pos = Math.round(relTime/1000);//TODO ugly quick hack 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 public void next() { 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 { 73 74 75 if(ls.indexOf(curr)==0) prev=null;elseprev=ls.get(ls.indexOf(curr)-1);76 77 else prev=null; 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 if(n.x<c.x)next(); else prev();163 164 165 166 167 168 169 170 171 if(n.x>c.x)next(); else prev();172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 } 193 194 195 196 197 198 199 200 201 202 203 204 205 206 Point p2 = getEndpoint(); 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 {int a,b,length,lengthSeg;223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 long inc=(long) (timeSeg*ratio); 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 int pos = Math.round(relTime/1000);//TODO ugly quick hack 349 350 351 352 353 354 355 356 357 358 359 360 ani=new TimerTask() { 361 362 363 public void run() { 364 365 366 367 368 369 t.schedule(ani,1000,1000); 370 371 372 373 374 375 376 377 t=null; 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 19 private List<WayPoint> ls; 20 private WayPoint prev,curr,next; 21 private WayPoint start; 22 private Timer t; 23 private TimerTask ani; //for moving trough the list 24 private boolean autoCenter; 25 26 27 public WayPoint getPrev() { 28 return prev; 29 } 30 31 public WayPoint getCurr() { 32 return curr; 33 } 34 35 public WayPoint getNext() { 36 return next; 37 } 38 39 public WayPoint getWaypoint(long relTime) 40 { 41 int pos = Math.round(relTime/1000);//TODO ugly quick hack 42 return ls.get(pos); 43 } 44 45 public GpsPlayer(List<WayPoint> l) { 46 super(); 47 this.ls = l; 48 //set start position 49 start=ls.get(0); 50 prev=null; 51 curr=ls.get(0); 52 next=ls.get(1); 53 } 54 55 // one secure step forward 56 public void next() { 57 if(ls.indexOf(curr)+1<ls.size()) 58 { 59 prev=curr; 60 curr=next; 61 if(ls.indexOf(curr)+1==ls.size()) next=null; 62 else next=ls.get(ls.indexOf(curr)+1); 63 } 64 else next=null; 65 66 } 67 68 //one secure step backward 69 public void prev() 70 { 71 if(ls.indexOf(curr)>0) 72 { 73 next =curr; 74 curr=prev; 75 if(ls.indexOf(curr)==0) prev=null;else prev=ls.get(ls.indexOf(curr)-1); 76 } 77 else prev=null; 78 } 79 80 //select the given waypoint as center 81 public void jump(WayPoint p) 82 { 83 if(ls.contains(p)) 84 { 85 curr=p; 86 if(ls.indexOf(curr)>0) 87 { 88 prev=ls.get(ls.indexOf(curr)-1); 89 } 90 else prev=null; 91 if(ls.indexOf(curr)+1<ls.size()) 92 { 93 next=ls.get(ls.indexOf(curr)+1); 94 } 95 else next=null; 96 } 97 } 98 99 //walk k waypoints forward/backward 100 public void jumpRel(int k) 101 { 102 103 if ((ls.indexOf(curr)+k>0)&&(ls.indexOf(curr)<ls.size())) //check range 104 { 105 jump(ls.get(ls.indexOf(curr)+k)); 106 } 107 Main.map.mapView.repaint(); //seperate modell and view logic... 108 } 109 110 //select the k-th waypoint 111 public void jump(int k) 112 { 113 if (k>0) 114 { 115 if ((ls.indexOf(curr)+k>0)&&(ls.indexOf(curr)<ls.size())) //check range 116 { 117 jump(ls.get(k)); 118 } 119 Main.map.mapView.repaint(); 120 } 121 } 122 123 //go to the position at the timecode e.g.g "14:00:01"; 124 public void jump(Time GPSAbsTime) 125 { 126 jump(getWaypoint(GPSAbsTime.getTime()-start.getTime().getTime())); //TODO replace Time by Date? 127 } 128 129 //go to the position at 130 public void jump(Date GPSDate) 131 { 132 long s,m,h,diff; 133 //calculate which waypoint is at the offset 134 System.out.println(start.getTime()); 135 System.out.println(start.getTime().getHours()+":"+start.getTime().getMinutes()+":"+start.getTime().getSeconds()); 136 s=GPSDate.getSeconds()-start.getTime().getSeconds(); 137 m=GPSDate.getMinutes()-start.getTime().getMinutes(); 138 h=GPSDate.getHours()-start.getTime().getHours(); 139 diff=s*1000+m*60*1000+h*60*60*1000; //TODO ugly hack but nothing else works right 140 jump(getWaypoint(diff)); 141 } 142 143 //gets only points on the line of the GPS track (between waypoints) nearby the point m 144 private Point getInterpolated(Point m) 145 { 146 Point leftP,rightP,highP,lowP; 147 boolean invalid = false; //when we leave this segment 148 Point p1 = Main.map.mapView.getPoint(getCurr().getEastNorth()); 149 Point p2 = getEndpoint(); 150 //determine which point is what 151 leftP=getLeftPoint(p1, p2); 152 rightP=getRightPoint(p1,p2); 153 highP=getHighPoint(p1, p2); 154 lowP=getLowPoint(p1, p2); 155 if(getNext()!=null) 156 { 157 //we might switch to one neighbor segment 158 if(m.x<leftP.x) 159 { 160 Point c = Main.map.mapView.getPoint(getCurr().getEastNorth()); 161 Point n = Main.map.mapView.getPoint(getNext().getEastNorth()); 162 if(n.x<c.x) next(); else prev(); 163 invalid=true; 164 m=leftP; 165 System.out.println("entering left segment"); 166 } 167 if(m.x>rightP.x) 168 { 169 Point c = Main.map.mapView.getPoint(getCurr().getEastNorth()); 170 Point n = Main.map.mapView.getPoint(getNext().getEastNorth()); 171 if(n.x>c.x) next(); else prev(); 172 invalid=true; 173 m=rightP; 174 System.out.println("entering right segment"); 175 } 176 if(!invalid) 177 { 178 float slope = getSlope(highP, lowP); 179 m.y = highP.y+Math.round(slope*(m.x-highP.x)); 180 } 181 } 182 else 183 { 184 //currently we are at the end 185 if(m.x>rightP.x) 186 { 187 m=rightP; //we can't move anywhere 188 } 189 else 190 { 191 prev(); //walk back to the segment before 192 } 193 } 194 return m; 195 } 196 197 //returns a point on the p% of the current selected segment 198 private Point getInterpolated(float percent) 199 { 200 201 int dX,dY; 202 Point p; 203 Point leftP,rightP; 204 Point c = Main.map.mapView.getPoint(getCurr().getEastNorth()); 205 Point p1 = Main.map.mapView.getPoint(getCurr().getEastNorth()); 206 Point p2 = getEndpoint(); 207 //determine which point is what 208 leftP=getLeftPoint(p1, p2); 209 rightP=getRightPoint(p1,p2); 210 //we will never go over the segment 211 percent=percent/100; 212 dX=Math.round((rightP.x-leftP.x)*percent); 213 dY=Math.round((rightP.y-leftP.y)*percent); 214 //move in the right direction 215 p=new Point(rightP.x-dX,rightP.y-dY); 216 217 return p; 218 } 219 220 //gets further infos for a point between two Waypoints 221 public WayPoint getInterpolatedWaypoint(Point m) 222 { int a,b,length,lengthSeg; 223 long timeSeg; 224 float ratio; 225 Time base; 226 Point p2; 227 228 Point curr =Main.map.mapView.getPoint(getCurr().getEastNorth()); 229 m =getInterpolated(m); //get the right position 230 //get the right time 231 p2=getEndpoint(); 232 if (getNext()!=null) 233 { 234 timeSeg=getNext().getTime().getTime()-getCurr().getTime().getTime(); 235 } 236 else 237 { 238 timeSeg=-(getPrev().getTime().getTime()-getCurr().getTime().getTime()); 239 } 240 WayPoint w =new WayPoint(Main.map.mapView.getLatLon(m.x, m.y)); 241 //calc total traversal length 242 lengthSeg = getTraversalLength(p2, curr); 243 length = getTraversalLength(p2, m); 244 length=lengthSeg-length; 245 //calc time difference 246 ratio=(float)length/(float)lengthSeg; 247 long inc=(long) (timeSeg*ratio); 248 long old = getCurr().getTime().getTime(); 249 old=old+inc; 250 Date t = new Date(old); 251 w.time = t.getTime()/1000; //TODO need better way to set time and sync it 252 SimpleDateFormat df = new SimpleDateFormat("hh:mm:ss:S"); 253 /*System.out.print(length+"px "); 254 System.out.print(ratio+"% "); 255 System.out.print(inc+"ms "); 256 System.out.println(df.format(t.getTime()));+*/ 257 System.out.println(df.format(w.getTime())); 258 //TODO we have to publish the new date to the node... 259 return w; 260 } 261 262 //returns a point and time for the current segment 263 private WayPoint getInterpolatedWaypoint(float percentage) 264 { 265 Point p = getInterpolated(percentage); 266 WayPoint w =new WayPoint(Main.map.mapView.getLatLon(p.x, p.y)); 267 return w; 268 } 269 270 //returns n points on the current segment 271 public List<WayPoint> getInterpolatedLine(int interval) 272 { 273 List<WayPoint> ls; 274 Point p2; 275 float step; 276 int length; 277 278 step=100/(float)interval; 279 ls=new LinkedList<WayPoint>(); 280 for(float i=step;i<100;i+=step) 281 { 282 ls.add(getInterpolatedWaypoint(i)); 283 } 284 return ls; 285 } 286 287 private Point getLeftPoint(Point p1,Point p2) 288 { 289 if(p1.x<p2.x) return p1; else return p2; 290 } 291 292 private Point getRightPoint(Point p1, Point p2) 293 { 294 if(p1.x>p2.x) return p1; else return p2; 295 } 296 297 private Point getHighPoint(Point p1, Point p2) 298 { 299 if(p1.y<p2.y)return p1; else return p2; 300 } 301 302 private Point getLowPoint(Point p1, Point p2) 303 { 304 if(p1.y>p2.y)return p1; else return p2; 305 } 306 307 private Point getEndpoint() { 308 if(getNext()!=null) 309 { 310 return Main.map.mapView.getPoint(getNext().getEastNorth()); 311 } 312 else 313 { 314 return Main.map.mapView.getPoint(getPrev().getEastNorth()); 315 } 316 317 } 318 319 private float getSlope(Point highP, Point lowP) { 320 float slope=(float)(highP.y-lowP.y) / (float)(highP.x - lowP.x); 321 return slope; 322 } 323 324 private int getTraversalLength(Point p2, Point curr) { 325 int a; 326 int b; 327 int lengthSeg; 328 a=Math.abs(curr.x-p2.x); 329 b=Math.abs(curr.y-p2.y); 330 lengthSeg= (int) Math.sqrt(Math.pow(a, 2)+Math.pow(b, 2)); 331 return lengthSeg; 332 } 333 334 //returns time in ms relatie to startpoint 335 public long getRelativeTime() 336 { 337 return getRelativeTime(curr); 338 } 339 340 public long getRelativeTime(WayPoint p) 341 { 342 return p.getTime().getTime()-start.getTime().getTime(); //TODO assumes timeintervall is constant!!!! 343 } 344 345 346 //jumps to a specific time 347 public void jump(long relTime) { 348 int pos = Math.round(relTime/1000);//TODO ugly quick hack 349 jump(pos); 350 //if (autoCenter) Main.map.mapView. 351 } 352 353 //toggles walking along the track 354 public void play() 355 { /* 356 if (t==null) 357 { 358 //start 359 t= new Timer(); 360 ani=new TimerTask() { 361 @Override 362 //some cheap animation stuff 363 public void run() { 364 next(); 365 if(autoCenter) Main.map.mapView.zoomTo(getCurr().getEastNorth()); 366 Main.map.mapView.repaint(); 367 } 368 }; 369 t.schedule(ani,1000,1000); 370 } 371 else 372 { 373 //stop 374 ani.cancel(); 375 ani=null; 376 t.cancel(); 377 t=null; 378 }*/ 379 } 380 381 public long getLength() { 382 return ls.size()*1000; //FIXME this is a poor hack 383 } 384 385 public void setAutoCenter(boolean b) 386 { 387 this.autoCenter=b; 388 } 389 390 public List<WayPoint> getTrack() 391 { 392 return ls; 393 } 394 395 396 397 398 398 } -
applications/editors/josm/plugins/videomapping/src/org/openstreetmap/josm/plugins/videomapping/PlayerObserver.java
r22690 r23193 3 3 //an Interface for communication for both players 4 4 public interface PlayerObserver { 5 6 7 5 void playing(long time); 6 void jumping(long time); 7 void metadata(long time,boolean subtitles); 8 8 9 9 } -
applications/editors/josm/plugins/videomapping/src/org/openstreetmap/josm/plugins/videomapping/PositionLayer.java
r23173 r23193 55 55 //Basic rendering and GPS layer interaction 56 56 public class PositionLayer extends Layer implements MouseListener,MouseMotionListener { 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 Main.map.mapView.addMouseMotionListener(this); 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 57 private static Set<PlayerObserver> observers = new HashSet<PlayerObserver>(); //we have to implement our own Observer pattern 58 private List<WayPoint> ls; 59 public GpsPlayer player; 60 private boolean dragIcon=false; //do we move the icon by hand? 61 private WayPoint iconPosition; 62 private Point mouse; 63 private ImageIcon icon; 64 private SimpleDateFormat mins; 65 private SimpleDateFormat ms; 66 private SimpleDateFormat gpsTimeCode; 67 private GPSVideoPlayer gps; 68 69 public PositionLayer(String name, final List<WayPoint> ls) { 70 super(name); 71 this.ls=ls; 72 player= new GpsPlayer(ls); 73 icon = new ImageIcon("images/videomapping.png"); 74 mins = new SimpleDateFormat("hh:mm:ss:S"); 75 ms= new SimpleDateFormat("mm:ss"); 76 gpsTimeCode= new SimpleDateFormat("hh:mm:ss"); 77 Main.map.mapView.addMouseListener(this); 78 Main.map.mapView.addMouseMotionListener(this); 79 80 } 81 82 83 @Override 84 public Icon getIcon() { 85 return icon; 86 } 87 88 @Override 89 public Object getInfoComponent() { 90 String temp; 91 String sep=System.getProperty("line.separator"); 92 temp=tr("{0} {1}% of GPS track",gps.getVideo().getName(),gps.getCoverage()*10+sep); 93 temp=temp+gps.getNativePlayerInfos(); 94 return temp; 95 } 96 97 @Override 98 public Component[] getMenuEntries() { 99 99 return new Component[]{ 100 100 new JMenuItem(LayerListDialog.getInstance().createShowHideLayerAction(this)), … … 104 104 new JSeparator(), 105 105 new JMenuItem(new LayerListPopup.InfoAction(this))};//TODO here infos about the linked videos 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 icon.paintIcon(null, g, p.x-icon.getIconWidth()/2, p.y-icon.getIconHeight()/2); 182 183 184 185 186 187 188 189 190 icon.paintIcon(null, g, p.x-icon.getIconWidth()/2, p.y-icon.getIconHeight()/2); 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 { 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 public void mouseClicked(MouseEvent e) { 231 232 233 public void mouseEntered(MouseEvent arg0) { 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 public void mouseReleased(MouseEvent e) { 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 { 273 274 275 276 277 278 279 280 281 282 283 public void mouseDragged(MouseEvent e) { 284 285 { 286 287 288 289 290 291 292 293 294 295 public void mouseMoved(MouseEvent e) { 296 297 { 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 106 } 107 108 109 110 @Override 111 public String getToolTipText() { 112 return tr("Shows current position in the video"); 113 } 114 115 // no merging necessary 116 @Override 117 public boolean isMergable(Layer arg0) { 118 return false; 119 } 120 121 @Override 122 public void mergeFrom(Layer arg0) { 123 124 } 125 126 127 128 @Override 129 //Draw the current position, infos, waypoints 130 public void paint(Graphics2D g, MapView map, Bounds bound) { 131 Point p; 132 //TODO Source out redundant calculations 133 //TODO make icon transparent 134 //draw all GPS points 135 g.setColor(Color.YELLOW); //new Color(0,255,0,128) 136 for(WayPoint n: ls) { 137 p = Main.map.mapView.getPoint(n.getEastNorth()); 138 g.drawOval(p.x - 2, p.y - 2, 4, 4); 139 } 140 //draw synced points 141 g.setColor(Color.GREEN); 142 for(WayPoint n: ls) { 143 if(n.attr.containsKey("synced")) 144 { 145 p = Main.map.mapView.getPoint(n.getEastNorth()); 146 g.drawOval(p.x - 2, p.y - 2, 4, 4); 147 } 148 } 149 //draw current segment points 150 g.setColor(Color.YELLOW); 151 if(player.getPrev()!=null) 152 { 153 p = Main.map.mapView.getPoint(player.getPrev().getEastNorth()); 154 g.drawOval(p.x - 2, p.y - 2, 4, 4); 155 Point p2 = Main.map.mapView.getPoint(player.getCurr().getEastNorth()); 156 g.drawLine(p.x, p.y, p2.x, p2.y); 157 } 158 if(player.getNext()!=null) 159 { 160 p = Main.map.mapView.getPoint(player.getNext().getEastNorth()); 161 g.drawOval(p.x - 2, p.y - 2, 4, 4); 162 Point p2 = Main.map.mapView.getPoint(player.getCurr().getEastNorth()); 163 g.drawLine(p.x, p.y, p2.x, p2.y); 164 } 165 //draw interpolated points 166 g.setColor(Color.CYAN); 167 g.setBackground(Color.CYAN); 168 LinkedList<WayPoint> ipo=(LinkedList<WayPoint>) player.getInterpolatedLine(5); 169 for (WayPoint wp : ipo) { 170 p=Main.map.mapView.getPoint(wp.getEastNorth()); 171 g.fillArc(p.x, p.y, 4, 4, 0, 360); 172 //g.drawOval(p.x - 2, p.y - 2, 4, 4); 173 } 174 //draw cam icon 175 g.setColor(Color.RED); 176 if(dragIcon) 177 { 178 if(iconPosition!=null) 179 { 180 p=Main.map.mapView.getPoint(iconPosition.getEastNorth()); 181 icon.paintIcon(null, g, p.x-icon.getIconWidth()/2, p.y-icon.getIconHeight()/2); 182 //g.drawString(mins.format(iconPosition.getTime()),p.x-10,p.y-10); //TODO when synced we might wan't to use a different layout 183 g.drawString(gpsTimeCode.format(iconPosition.getTime()),p.x-10,p.y-10); 184 } 185 } 186 else 187 { 188 if (player.getCurr()!=null){ 189 p=Main.map.mapView.getPoint(player.getCurr().getEastNorth()); 190 icon.paintIcon(null, g, p.x-icon.getIconWidth()/2, p.y-icon.getIconHeight()/2); 191 g.drawString(gpsTimeCode.format(player.getCurr().getTime()),p.x-10,p.y-10); 192 } 193 } 194 } 195 196 //finds the first waypoint that is nearby the given point 197 private WayPoint getNearestWayPoint(Point mouse) 198 { 199 final int MAX=10; 200 Point p; 201 Rectangle rect = new Rectangle(mouse.x-MAX/2,mouse.y-MAX/2,MAX,MAX); 202 //iterate through all possible notes 203 for(WayPoint n : ls) //TODO this is not very clever, what better way to find this WP? Hashmaps? Divide and Conquer? 204 { 205 p = Main.map.mapView.getPoint(n.getEastNorth()); 206 if (rect.contains(p)) 207 { 208 return n; 209 } 210 211 } 212 return null; 213 214 } 215 216 //upper left corner like rectangle 217 private Rectangle getIconRect() 218 { 219 Point p = Main.map.mapView.getPoint(player.getCurr().getEastNorth()); 220 return new Rectangle(p.x-icon.getIconWidth()/2,p.y-icon.getIconHeight()/2,icon.getIconWidth(),icon.getIconHeight()); 221 } 222 223 224 @Override 225 public void visitBoundingBox(BoundingXYVisitor arg0) { 226 // TODO don't know what to do here 227 228 } 229 230 public void mouseClicked(MouseEvent e) { 231 } 232 233 public void mouseEntered(MouseEvent arg0) { 234 } 235 236 public void mouseExited(MouseEvent arg0) { 237 } 238 239 //init drag&drop 240 public void mousePressed(MouseEvent e) { 241 if(e.getButton() == MouseEvent.BUTTON1) { 242 //is it on the cam icon? 243 if (player.getCurr()!=null) 244 { 245 if (getIconRect().contains(e.getPoint())) 246 { 247 mouse=e.getPoint(); 248 dragIcon=true; 249 } 250 } 251 } 252 253 } 254 255 // 256 public void mouseReleased(MouseEvent e) { 257 //only leftclicks on our layer 258 if(e.getButton() == MouseEvent.BUTTON1) { 259 if(dragIcon) 260 { 261 dragIcon=false; 262 } 263 else 264 { 265 //simple click 266 WayPoint wp = getNearestWayPoint(e.getPoint()); 267 if(wp!=null) 268 { 269 player.jump(wp); 270 //jump if we know position 271 if(wp.attr.containsKey("synced")) 272 { 273 if(gps!=null) notifyObservers(player.getRelativeTime()); //call videoplayers to set right position 274 } 275 } 276 } 277 Main.map.mapView.repaint(); 278 } 279 280 } 281 282 //slide and restrict during movement 283 public void mouseDragged(MouseEvent e) { 284 if(dragIcon) 285 { 286 mouse=e.getPoint(); 287 //restrict to GPS track 288 iconPosition=player.getInterpolatedWaypoint(mouse); 289 290 Main.map.mapView.repaint(); 291 } 292 } 293 294 //visualize drag&drop 295 public void mouseMoved(MouseEvent e) { 296 if (player.getCurr()!=null) 297 { 298 if (getIconRect().contains(e.getPoint())) 299 { 300 Main.map.mapView.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 301 } 302 else 303 { 304 Main.map.mapView.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 305 } 306 } 307 308 } 309 310 public void setGPSPlayer(GPSVideoPlayer player) { 311 this.gps = player; 312 313 } 314 315 public static void addObserver(PlayerObserver observer) { 316 316 317 317 observers.add(observer); -
applications/editors/josm/plugins/videomapping/src/org/openstreetmap/josm/plugins/videomapping/VideoMappingPlugin.java
r23173 r23193 49 49 //Here we manage properties and start the other classes 50 50 public class VideoMappingPlugin extends Plugin implements LayerChangeListener{ 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 GPSTrack=((GpxLayer) newLayer).data; 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 public void layerRemoved(Layer arg0) { 113 114 115 116 117 118 119 120 public void actionPerformed(ActionEvent arg0) { 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 public void actionPerformed(ActionEvent e) { 153 154 155 156 157 158 159 160 161 162 163 Vbackward = new JosmAction(tr("Jump To"), null, tr("jumps to the entered gps time"),null, false) { 164 165 166 167 168 169 170 171 { 172 173 } 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 saveSettings(); 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 VMenu.add(VAdd); 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 String temp; 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 51 private JMenu VMenu,VDeinterlacer; 52 private GpxData GPSTrack; 53 private List<WayPoint> ls; 54 private JosmAction VAdd,VRemove,VStart,Vbackward,Vforward,VJump,Vfaster,Vslower,Vloop; 55 private JRadioButtonMenuItem VIntBob,VIntNone,VIntLinear; 56 private JCheckBoxMenuItem VCenterIcon,VSubTitles; 57 private JMenuItem VJumpLength,VLoopLength; 58 private GPSVideoPlayer player; 59 private PositionLayer layer; 60 private final String VM_DEINTERLACER="videomapping.deinterlacer"; //where we store settings 61 private final String VM_MRU="videomapping.mru"; 62 private final String VM_AUTOCENTER="videomapping.autocenter"; 63 private final String VM_JUMPLENGTH="videomapping.jumplength"; 64 private final String VM_LOOPLENGTH="videomapping.looplength"; 65 private boolean autocenter; 66 private String deinterlacer; 67 private Integer jumplength,looplength; 68 private String mru; 69 //TODO What more to store during sessions? Size/Position 70 71 72 public VideoMappingPlugin(PluginInformation info) { 73 super(info); 74 MapView.addLayerChangeListener(this); 75 //Register for GPS menu 76 VMenu = Main.main.menu.addMenu(" Video", KeyEvent.VK_V, Main.main.menu.defaultMenuPos,ht("/Plugin/Videomapping"));//TODO no more ugly " video" hack 77 addMenuItems(); 78 enableControlMenus(true); 79 loadSettings(); 80 applySettings(); 81 //further plugin informations are provided by build.xml properties 82 } 83 84 //only use with GPS and own layers 85 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 86 System.out.println(newLayer); 87 if (newLayer instanceof GpxLayer) 88 { 89 VAdd.setEnabled(true); 90 GPSTrack=((GpxLayer) newLayer).data; 91 //TODO append to GPS Layer menu 92 } 93 else 94 {/* 95 VAdd.setEnabled(false); 96 if(newLayer instanceof PositionLayer) 97 { 98 enableControlMenus(true); 99 } 100 else 101 { 102 enableControlMenus(false); 103 }*/ 104 } 105 106 } 107 108 public void layerAdded(Layer arg0) { 109 activeLayerChange(null,arg0); 110 } 111 112 public void layerRemoved(Layer arg0) { 113 } //well ok we have a local copy of the GPS track.... 114 115 //register main controls 116 private void addMenuItems() { 117 VAdd= new JosmAction(tr("Import Video"),"videomapping",tr("Sync a video against this GPS track"),null,false) { 118 private static final long serialVersionUID = 1L; 119 120 public void actionPerformed(ActionEvent arg0) { 121 JFileChooser fc = new JFileChooser("C:\\TEMP\\"); 122 //fc.setSelectedFile(new File(mru)); 123 if(fc.showOpenDialog(Main.main.parent)!=JFileChooser.CANCEL_OPTION) 124 { 125 saveSettings(); 126 ls=copyGPSLayer(GPSTrack); 127 enableControlMenus(true); 128 layer = new PositionLayer(fc.getSelectedFile().getName(),ls); 129 Main.main.addLayer(layer); 130 player = new GPSVideoPlayer(fc.getSelectedFile(), layer.player); 131 //TODO Check here if we can sync allready now 132 layer.setGPSPlayer(player); 133 layer.addObserver(player); 134 VAdd.setEnabled(false); 135 VRemove.setEnabled(true); 136 player.setSubtitleAction(VSubTitles); 137 } 138 } 139 140 }; 141 VRemove= new JosmAction(tr("Remove Video"),"videomapping",tr("removes current video from layer"),null,false) { 142 private static final long serialVersionUID = 1L; 143 144 public void actionPerformed(ActionEvent arg0) { 145 player.removeVideo(); 146 } 147 }; 148 149 VStart = new JosmAction(tr("Play/Pause"), "audio-playpause", tr("starts/pauses video playback"), 150 Shortcut.registerShortcut("videomapping:startstop","",KeyEvent.VK_NUMPAD5, Shortcut.GROUP_DIRECT), false) { 151 152 public void actionPerformed(ActionEvent e) { 153 if(player.playing()) player.pause(); else player.play(); 154 } 155 }; 156 Vbackward = new JosmAction(tr("Backward"), "audio-prev", tr("jumps n sec back"), 157 Shortcut.registerShortcut("videomapping:backward","",KeyEvent.VK_NUMPAD4, Shortcut.GROUP_DIRECT), false) { 158 public void actionPerformed(ActionEvent e) { 159 player.backward(); 160 161 } 162 }; 163 Vbackward = new JosmAction(tr("Jump To"), null, tr("jumps to the entered gps time"),null, false) { 164 public void actionPerformed(ActionEvent e) { 165 String s =JOptionPane.showInputDialog(tr("please enter GPS timecode"),"10:07:57"); 166 SimpleDateFormat format= new SimpleDateFormat("hh:mm:ss"); 167 Date t; 168 try { 169 t = format.parse(s); 170 if (t!=null) 171 { 172 player.jumpToGPSTime(t.getTime()); 173 } 174 } catch (ParseException e1) { 175 // TODO Auto-generated catch block 176 e1.printStackTrace(); 177 } 178 179 } 180 }; 181 Vforward= new JosmAction(tr("Forward"), "audio-next", tr("jumps n sec forward"), 182 Shortcut.registerShortcut("videomapping:forward","",KeyEvent.VK_NUMPAD6, Shortcut.GROUP_DIRECT), false) { 183 184 public void actionPerformed(ActionEvent e) { 185 player.forward(); 186 187 } 188 }; 189 Vfaster= new JosmAction(tr("Faster"), "audio-faster", tr("faster playback"), 190 Shortcut.registerShortcut("videomapping:faster","",KeyEvent.VK_NUMPAD8, Shortcut.GROUP_DIRECT), false) { 191 192 public void actionPerformed(ActionEvent e) { 193 player.faster(); 194 195 } 196 }; 197 Vslower= new JosmAction(tr("Slower"), "audio-slower", tr("slower playback"), 198 Shortcut.registerShortcut("videomapping:slower","",KeyEvent.VK_NUMPAD2, Shortcut.GROUP_DIRECT), false) { 199 200 public void actionPerformed(ActionEvent e) { 201 player.slower(); 202 203 } 204 }; 205 Vloop= new JosmAction(tr("Loop"), null, tr("loops n sec around current position"), 206 Shortcut.registerShortcut("videomapping:loop","",KeyEvent.VK_NUMPAD7, Shortcut.GROUP_DIRECT), false) { 207 208 public void actionPerformed(ActionEvent e) { 209 player.loop(); 210 211 } 212 }; 213 214 //now the options menu 215 VCenterIcon = new JCheckBoxMenuItem(new JosmAction(tr("Keep centered"), null, tr("follows the video icon automaticly"),null, false) { 216 217 public void actionPerformed(ActionEvent e) { 218 autocenter=VCenterIcon.isSelected(); 219 player.setAutoCenter(autocenter); 220 applySettings(); 221 saveSettings(); 222 223 } 224 }); 225 //now the options menu 226 VSubTitles = new JCheckBoxMenuItem(new JosmAction(tr("Subtitles"), null, tr("Show subtitles in video"),null, false) { 227 228 public void actionPerformed(ActionEvent e) { 229 player.toggleSubtitles(); 230 231 } 232 }); 233 234 VJumpLength = new JMenuItem(new JosmAction(tr("Jump length"), null, tr("Set the length of a jump"),null, false) { 235 236 public void actionPerformed(ActionEvent e) { 237 Object[] possibilities = {"200", "500", "1000", "2000", "10000"}; 238 String s = (String)JOptionPane.showInputDialog(Main.parent,tr("Jump in video for x ms"),tr("Jump length"),JOptionPane.QUESTION_MESSAGE,null,possibilities,jumplength); 239 jumplength=Integer.getInteger(s); 240 applySettings(); 241 saveSettings(); 242 } 243 }); 244 245 VLoopLength = new JMenuItem(new JosmAction(tr("Loop length"), null, tr("Set the length around a looppoint"),null, false) { 246 247 public void actionPerformed(ActionEvent e) { 248 Object[] possibilities = {"500", "1000", "3000", "5000", "10000"}; 249 String s = (String)JOptionPane.showInputDialog(Main.parent,tr("Jump in video for x ms"),tr("Loop length"),JOptionPane.QUESTION_MESSAGE,null,possibilities,looplength); 250 looplength=Integer.getInteger(s); 251 applySettings(); 252 saveSettings(); 253 254 } 255 }); 256 257 VDeinterlacer= new JMenu("Deinterlacer"); 258 VIntNone= new JRadioButtonMenuItem(new JosmAction(tr("none"), null, tr("no deinterlacing"),null, false) { 259 260 public void actionPerformed(ActionEvent e) { 261 deinterlacer=null; 262 applySettings(); 263 saveSettings(); 264 } 265 }); 266 VIntBob= new JRadioButtonMenuItem(new JosmAction("bob", null, tr("deinterlacing using line doubling"),null, false) { 267 268 public void actionPerformed(ActionEvent e) { 269 deinterlacer="bob"; 270 applySettings(); 271 saveSettings(); 272 } 273 }); 274 VIntLinear= new JRadioButtonMenuItem(new JosmAction("linear", null, tr("deinterlacing using linear interpolation"),null, false) { 275 276 public void actionPerformed(ActionEvent e) { 277 deinterlacer="linear"; 278 applySettings(); 279 saveSettings(); 280 } 281 }); 282 VDeinterlacer.add(VIntNone); 283 VDeinterlacer.add(VIntBob); 284 VDeinterlacer.add(VIntLinear); 285 286 VMenu.add(VAdd); 287 VMenu.add(VStart); 288 VMenu.add(Vbackward); 289 VMenu.add(Vforward); 290 VMenu.add(Vfaster); 291 VMenu.add(Vslower); 292 VMenu.add(Vloop); 293 VMenu.addSeparator(); 294 VMenu.add(VCenterIcon); 295 VMenu.add(VJumpLength); 296 VMenu.add(VLoopLength); 297 VMenu.add(VDeinterlacer); 298 VMenu.add(VSubTitles); 299 300 } 301 302 303 304 //we can only work on our own layer 305 private void enableControlMenus(boolean enabled) 306 { 307 VStart.setEnabled(enabled); 308 Vbackward.setEnabled(enabled); 309 Vforward.setEnabled(enabled); 310 Vloop.setEnabled(enabled); 311 } 312 313 //load all properties or set defaults 314 private void loadSettings() { 315 String temp; 316 temp=Main.pref.get(VM_AUTOCENTER); 317 if((temp!=null)&&(temp.length()!=0))autocenter=Boolean.getBoolean(temp); else autocenter=false; 318 temp=Main.pref.get(VM_DEINTERLACER); 319 if((temp!=null)&&(temp.length()!=0)) deinterlacer=Main.pref.get(temp); 320 temp=Main.pref.get(VM_JUMPLENGTH); 321 if((temp!=null)&&(temp.length()!=0)) jumplength=Integer.valueOf(temp); else jumplength=1000; 322 temp=Main.pref.get(VM_LOOPLENGTH); 323 if((temp!=null)&&(temp.length()!=0)) looplength=Integer.valueOf(temp); else looplength=6000; 324 temp=Main.pref.get(VM_MRU); 325 if((temp!=null)&&(temp.length()!=0)) mru=Main.pref.get(VM_MRU);else mru=System.getProperty("user.home"); 326 } 327 328 private void applySettings(){ 329 //Internals 330 if(player!=null) 331 { 332 player.setAutoCenter(autocenter); 333 player.setDeinterlacer(deinterlacer); 334 player.setJumpLength(jumplength); 335 player.setLoopLength(looplength); 336 } 337 //GUI 338 VCenterIcon.setSelected(autocenter); 339 VIntNone.setSelected(true); 340 if(deinterlacer=="bob")VIntBob.setSelected(true); 341 if(deinterlacer=="linear")VIntLinear.setSelected(true); 342 343 } 344 345 private void saveSettings(){ 346 Main.pref.put(VM_AUTOCENTER, autocenter); 347 Main.pref.put(VM_DEINTERLACER, deinterlacer); 348 Main.pref.put(VM_JUMPLENGTH, jumplength.toString()); 349 Main.pref.put(VM_LOOPLENGTH, looplength.toString()); 350 Main.pref.put(VM_MRU, mru); 351 } 352 353 //make a flat copy 354 private List<WayPoint> copyGPSLayer(GpxData route) 355 { 356 ls = new LinkedList<WayPoint>(); 357 357 for (GpxTrack trk : route.tracks) { 358 358 for (GpxTrackSegment segment : trk.getSegments()) { … … 362 362 Collections.sort(ls); //sort basing upon time 363 363 return ls; 364 364 } 365 365 } -
applications/editors/josm/plugins/videomapping/src/org/openstreetmap/josm/plugins/videomapping/video/GPSVideoFile.java
r21631 r23193 4 4 // a specific synced video 5 5 public class GPSVideoFile extends File{ 6 7 8 9 10 11 6 public long offset; //time difference in ms between GPS and Video track 7 8 public GPSVideoFile(File f, long offset) { 9 super(f.getAbsoluteFile().toString()); 10 this.offset=offset; 11 } 12 12 13 13 } -
applications/editors/josm/plugins/videomapping/src/org/openstreetmap/josm/plugins/videomapping/video/GPSVideoPlayer.java
r23173 r23193 22 22 //combines video and GPS playback, major control has the video player 23 23 public class GPSVideoPlayer implements PlayerObserver{ 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 if(subtTitleComponent!=null) subtTitleComponent.setSelected(subtitles); 77 78 79 80 t = new Timer(); 81 82 83 84 85 86 87 88 89 90 91 92 end=gps.getWaypoint(gps.getLength()); 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 } 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 //when not synced we can just move the icon to the right position 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 24 Timer t; 25 TimerTask updateGPSTrack; 26 private GpsPlayer gps; 27 private SimpleVideoPlayer video; 28 private JButton syncBtn; 29 private GPSVideoFile file; 30 private boolean synced=false; //do we playback the players together? 31 private JCheckBoxMenuItem subtTitleComponent; 32 33 34 public GPSVideoPlayer(File f, final GpsPlayer pl) { 35 super(); 36 this.gps = pl; 37 //test sync 38 video = new SimpleVideoPlayer(); 39 /* 40 long gpsT=(9*60+20)*1000; 41 long videoT=10*60*1000+5*1000; 42 setFile(new GPSVideoFile(f, gpsT-videoT)); */ 43 setFile(new GPSVideoFile(f, 0L)); 44 //add Sync Button to the Player 45 syncBtn= new JButton("sync"); 46 syncBtn.setBackground(Color.RED); 47 syncBtn.addActionListener(new ActionListener() { 48 //do a sync 49 public void actionPerformed(ActionEvent e) { 50 long diff=gps.getRelativeTime()-video.getTime(); 51 file= new GPSVideoFile(file, diff); 52 syncBtn.setBackground(Color.GREEN); 53 synced=true; 54 markSyncedPoints(); 55 video.play(); 56 //gps.play(); 57 } 58 }); 59 setAsyncMode(true); 60 video.addComponent(syncBtn); 61 //a observer to communicate 62 SimpleVideoPlayer.addObserver(new PlayerObserver() { //TODO has o become this 63 64 public void playing(long time) { 65 //sync the GPS back 66 if(synced) gps.jump(getGPSTime(time)); 67 68 } 69 70 public void jumping(long time) { 71 72 } 73 74 //a push way to set video attirbutes 75 public void metadata(long time, boolean subtitles) { 76 if(subtTitleComponent!=null) subtTitleComponent.setSelected(subtitles); 77 } 78 79 }); 80 t = new Timer(); 81 } 82 83 //marks all points that are covered by video AND GPS track 84 private void markSyncedPoints() { 85 //GPS or video stream starts first in time? 86 WayPoint start,end; 87 long t; 88 if(gps.getLength()<video.getLength()) 89 { 90 //GPS is within video timeperiod 91 start=gps.getWaypoint(0); 92 end=gps.getWaypoint(gps.getLength()); 93 } 94 else 95 { 96 //video is within gps timeperiod 97 t=getGPSTime(0); 98 if(t<0) t=0; 99 start=gps.getWaypoint(t); 100 end=gps.getWaypoint(getGPSTime(video.getLength())); 101 } 102 //mark as synced 103 List<WayPoint> ls = gps.getTrack().subList(gps.getTrack().indexOf(start), gps.getTrack().indexOf(end)); 104 105 for (WayPoint wp : ls) { 106 wp.attr.put("synced", "true"); 107 } 108 } 109 110 public void setAsyncMode(boolean b) 111 { 112 if(b) 113 { 114 syncBtn.setVisible(true); 115 } 116 else 117 { 118 syncBtn.setVisible(false); 119 } 120 } 121 122 123 public void setFile(GPSVideoFile f) 124 { 125 126 file=f; 127 video.setFile(f.getAbsoluteFile()); 128 //video.play(); 129 } 130 131 public void play(long gpsstart) 132 { 133 //video is already playing 134 jumpToGPSTime(gpsstart); 135 gps.jump(gpsstart); 136 //gps.play(); 137 } 138 139 public void play() 140 { 141 video.play(); 142 } 143 144 public void pause() 145 { 146 video.pause(); 147 } 148 149 //jumps in video to the corresponding linked time 150 public void jumpToGPSTime(Time GPSTime) 151 { 152 gps.jump(GPSTime); 153 } 154 155 //jumps in video to the corresponding linked time 156 public void jumpToGPSTime(long gpsT) 157 { 158 if(!synced) 159 { 160 //when not synced we can just move the icon to the right position 161 gps.jump(new Date(gpsT)); 162 Main.map.mapView.repaint(); 163 } 164 video.jump(getVideoTime(gpsT)); 165 } 166 167 //calc synced timecode from video 168 private long getVideoTime(long GPStime) 169 { 170 return GPStime-file.offset; 171 } 172 173 //calc corresponding GPS time 174 private long getGPSTime(long videoTime) 175 { 176 return videoTime+file.offset; 177 } 178 179 180 181 public void setJumpLength(Integer integer) { 182 video.setJumpLength(integer); 183 184 } 185 186 public void setLoopLength(Integer integer) { 187 video.setLoopLength(integer); 188 189 } 190 191 public boolean isSynced() 192 { 193 return isSynced(); 194 } 195 196 public void loop() { 197 video.loop(); 198 199 } 200 201 public void forward() { 202 video.forward(); 203 204 } 205 206 public void backward() { 207 video.backward(); 208 209 } 210 211 public void removeVideo() { 212 video.removeVideo(); 213 214 } 215 216 public File getVideo() { 217 return file; 218 } 219 220 public float getCoverage() { 221 return gps.getLength()/video.getLength(); 222 } 223 224 public void setDeinterlacer(String string) { 225 video.setDeinterlacer(string); 226 227 } 228 229 public void setAutoCenter(boolean selected) { 230 gps.setAutoCenter(selected); 231 232 } 233 234 235 //not called by GPS 236 public boolean playing() { 237 return video.playing(); 238 } 239 240 //when we clicked on the layer, here we update the video position 241 public void jumping(long time) { 242 if(synced) jumpToGPSTime(gps.getRelativeTime()); 243 244 } 245 246 public String getNativePlayerInfos() { 247 return video.getNativePlayerInfos(); 248 } 249 250 public void faster() { 251 video.faster(); 252 253 } 254 255 public void slower() { 256 video.slower(); 257 258 } 259 260 public void playing(long time) { 261 // TODO Auto-generated method stub 262 263 } 264 265 public void toggleSubtitles() { 266 video.toggleSubs(); 267 268 } 269 270 public boolean hasSubtitles(){ 271 return video.hasSubtitles(); 272 } 273 274 public void setSubtitleAction(JCheckBoxMenuItem a) 275 { 276 subtTitleComponent=a; 277 } 278 279 public void metadata(long time, boolean subtitles) { 280 // TODO Auto-generated method stub 281 282 } 283 284 285 286 287 288 288 } -
applications/editors/josm/plugins/videomapping/src/org/openstreetmap/josm/plugins/videomapping/video/SimpleVideoPlayer.java
r22690 r23193 49 49 //basic class of a videoplayer for one video 50 50 public class SimpleVideoPlayer extends JFrame implements MediaPlayerEventListener, WindowListener{ 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 speed.setPaintTicks(true); 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 } 177 178 179 180 181 182 183 184 if(mp.isPlaying()) mp.pause(); else mp.play(); 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 } 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 51 private EmbeddedMediaPlayer mp; 52 private Timer t; 53 private JPanel screenPanel,controlsPanel; 54 private JSlider timeline; 55 private JButton play,back,forward; 56 private JToggleButton loop,mute; 57 private JSlider speed; 58 private Canvas scr; 59 private final String[] mediaOptions = {""}; 60 private boolean syncTimeline=false; 61 private boolean looping=false; 62 private SimpleDateFormat ms; 63 private static final Logger LOG = Logger.getLogger(MediaPlayerFactory.class); 64 private int jumpLength=1000; 65 private int loopLength=6000; 66 private static Set<PlayerObserver> observers = new HashSet<PlayerObserver>(); //we have to implement our own Observer pattern 67 68 public SimpleVideoPlayer() { 69 super(); 70 /*TODO new EnvironmentCheckerFactory().newEnvironmentChecker().checkEnvironment(); 71 * if(RuntimeUtil.isWindows()) { 72 vlcArgs.add("--plugin-path=" + WindowsRuntimeUtil.getVlcInstallDir() + "\\plugins"); 73 } 74 */ 75 try 76 { 77 //we don't need any options 78 String[] libvlcArgs = {""}; 79 String[] standardMediaOptions = {""}; 80 81 //System.out.println("libvlc version: " + LibVlc.INSTANCE.libvlc_get_version()); 82 //setup Media Player 83 //TODO we have to deal with unloading things.... 84 MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory(libvlcArgs); 85 FullScreenStrategy fullScreenStrategy = new DefaultFullScreenStrategy(this); 86 mp = mediaPlayerFactory.newMediaPlayer(fullScreenStrategy); 87 mp.setStandardMediaOptions(standardMediaOptions); 88 //setup GUI 89 setSize(400, 300); //later we apply movie size 90 setAlwaysOnTop(true); 91 createUI(); 92 setLayout(); 93 addListeners(); //registering shortcuts is task of the outer plugin class! 94 //embed vlc player 95 scr.setVisible(true); 96 setVisible(true); 97 mp.setVideoSurface(scr); 98 mp.addMediaPlayerEventListener(this); 99 //mp.pause(); 100 //jump(0); 101 //create updater 102 ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); 103 executorService.scheduleAtFixedRate(new Syncer(this), 0L, 1000L, TimeUnit.MILLISECONDS); 104 //setDefaultCloseOperation(EXIT_ON_CLOSE); 105 addWindowListener(this); 106 } 107 catch (NoClassDefFoundError e) 108 { 109 System.err.println(tr("Unable to find JNA Java library!")); 110 } 111 catch (UnsatisfiedLinkError e) 112 { 113 System.err.println(tr("Unable to find native libvlc library!")); 114 } 115 116 } 117 118 private void createUI() { 119 //setIconImage(); 120 ms = new SimpleDateFormat("hh:mm:ss"); 121 scr=new Canvas(); 122 timeline = new JSlider(0,100,0); 123 timeline.setMajorTickSpacing(10); 124 timeline.setMajorTickSpacing(5); 125 timeline.setPaintTicks(true); 126 //TODO we need Icons instead 127 play= new JButton(tr("play")); 128 back= new JButton("<"); 129 forward= new JButton(">"); 130 loop= new JToggleButton(tr("loop")); 131 mute= new JToggleButton(tr("mute")); 132 speed = new JSlider(-200,200,0); 133 speed.setMajorTickSpacing(100); 134 speed.setPaintTicks(true); 135 speed.setOrientation(Adjustable.VERTICAL); 136 Hashtable labelTable = new Hashtable(); 137 labelTable.put( new Integer( 0 ), new JLabel("1x") ); 138 labelTable.put( new Integer( -200 ), new JLabel("-2x") ); 139 labelTable.put( new Integer( 200 ), new JLabel("2x") ); 140 speed.setLabelTable( labelTable ); 141 speed.setPaintLabels(true); 142 } 143 144 //creates a layout like the most mediaplayers are... 145 private void setLayout() { 146 this.setLayout(new BorderLayout()); 147 screenPanel=new JPanel(); 148 screenPanel.setLayout(new BorderLayout()); 149 controlsPanel=new JPanel(); 150 controlsPanel.setLayout(new FlowLayout()); 151 add(screenPanel,BorderLayout.CENTER); 152 add(controlsPanel,BorderLayout.SOUTH); 153 //fill screen panel 154 screenPanel.add(scr,BorderLayout.CENTER); 155 screenPanel.add(timeline,BorderLayout.SOUTH); 156 screenPanel.add(speed,BorderLayout.EAST); 157 controlsPanel.add(play); 158 controlsPanel.add(back); 159 controlsPanel.add(forward); 160 controlsPanel.add(loop); 161 controlsPanel.add(mute); 162 loop.setSelected(false); 163 mute.setSelected(false); 164 } 165 166 //add UI functionality 167 private void addListeners() { 168 timeline.addChangeListener(new ChangeListener() { 169 public void stateChanged(ChangeEvent e) { 170 if(!syncTimeline) //only if user moves the slider by hand 171 { 172 if(!timeline.getValueIsAdjusting()) //and the slider is fixed 173 { 174 //recalc to 0.x percent value 175 mp.setPosition((float)timeline.getValue()/100.0f); 176 } 177 } 178 } 179 }); 180 181 play.addActionListener(new ActionListener() { 182 183 public void actionPerformed(ActionEvent arg0) { 184 if(mp.isPlaying()) mp.pause(); else mp.play(); 185 } 186 }); 187 188 back.addActionListener(new ActionListener() { 189 190 public void actionPerformed(ActionEvent arg0) { 191 backward(); 192 } 193 }); 194 195 forward.addActionListener(new ActionListener() { 196 197 public void actionPerformed(ActionEvent arg0) { 198 forward(); 199 } 200 }); 201 202 loop.addActionListener(new ActionListener() { 203 204 public void actionPerformed(ActionEvent arg0) { 205 loop(); 206 } 207 }); 208 209 mute.addActionListener(new ActionListener() { 210 211 public void actionPerformed(ActionEvent arg0) { 212 mute(); 213 } 214 }); 215 216 speed.addChangeListener(new ChangeListener() { 217 218 public void stateChanged(ChangeEvent arg0) { 219 if(!speed.getValueIsAdjusting()&&(mp.isPlaying())) 220 { 221 int perc = speed.getValue(); 222 float ratio= (float) (perc/400f*1.75); 223 ratio=ratio+(9/8); 224 mp.setRate(ratio); 225 } 226 227 } 228 }); 229 230 } 231 232 public void finished(MediaPlayer arg0) { 233 234 } 235 236 public void lengthChanged(MediaPlayer arg0, long arg1) { 237 238 } 239 240 public void metaDataAvailable(MediaPlayer arg0, VideoMetaData data) { 241 final float perc = 0.5f; 242 Dimension org=data.getVideoDimension(); 243 scr.setSize(new Dimension((int)(org.width*perc), (int)(org.height*perc))); 244 pack(); 245 //send out metadatas to all observers 246 for (PlayerObserver o : observers) { 247 247 o.metadata(0, hasSubtitles()); 248 248 } 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 public void windowActivated(WindowEvent arg0) {}273 274 public void windowClosed(WindowEvent arg0) {}275 276 277 249 } 250 251 public void paused(MediaPlayer arg0) { 252 253 } 254 255 public void playing(MediaPlayer arg0) { 256 257 } 258 259 public void positionChanged(MediaPlayer arg0, float arg1) { 260 261 } 262 263 public void stopped(MediaPlayer arg0) { 264 265 } 266 267 public void timeChanged(MediaPlayer arg0, long arg1) { 268 269 } 270 271 272 public void windowActivated(WindowEvent arg0) { } 273 274 public void windowClosed(WindowEvent arg0) { } 275 276 //we have to unload and disconnect to the VLC engine 277 public void windowClosing(WindowEvent evt) { 278 278 if(LOG.isDebugEnabled()) {LOG.debug("windowClosing(evt=" + evt + ")");} 279 279 mp.release(); … … 282 282 } 283 283 284 public void windowDeactivated(WindowEvent arg0) {}285 286 public void windowDeiconified(WindowEvent arg0) {}287 288 public void windowIconified(WindowEvent arg0) {}289 290 public void windowOpened(WindowEvent arg0) { } 291 292 293 294 295 296 pack(); 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 public long getLength() { 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 else 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 284 public void windowDeactivated(WindowEvent arg0) { } 285 286 public void windowDeiconified(WindowEvent arg0) { } 287 288 public void windowIconified(WindowEvent arg0) { } 289 290 public void windowOpened(WindowEvent arg0) { } 291 292 public void setFile(File f) 293 { 294 String mediaPath = f.getAbsoluteFile().toString(); 295 mp.playMedia(mediaPath, mediaOptions); 296 pack(); 297 } 298 299 public void play() 300 { 301 mp.play(); 302 } 303 304 public void jump(long time) 305 { 306 /*float pos = (float)mp.getLength()/(float)time; 307 mp.setPosition(pos);*/ 308 mp.setTime(time); 309 } 310 311 public long getTime() 312 { 313 return mp.getTime(); 314 } 315 316 public float getPosition() 317 { 318 return mp.getPosition(); 319 } 320 321 public boolean isPlaying() 322 { 323 return mp.isPlaying(); 324 } 325 326 //gets called by the Syncer thread to update all observers 327 public void updateTime () 328 { 329 if(mp.isPlaying()) 330 { 331 setTitle(ms.format(new Date(mp.getTime()))); 332 syncTimeline=true; 333 timeline.setValue(Math.round(mp.getPosition()*100)); 334 syncTimeline=false; 335 notifyObservers(mp.getTime()); 336 } 337 } 338 339 //allow externals to extend the ui 340 public void addComponent(JComponent c) 341 { 342 controlsPanel.add(c); 343 pack(); 344 } 345 346 public long getLength() { 347 return mp.getLength(); 348 } 349 350 public void setDeinterlacer(String string) { 351 mp.setDeinterlace(string); 352 353 } 354 355 public void setJumpLength(Integer integer) { 356 jumpLength=integer; 357 358 } 359 360 public void setLoopLength(Integer integer) { 361 loopLength = integer; 362 363 } 364 365 public void loop() { 366 if(looping) 367 { 368 t.cancel(); 369 looping=false; 370 } 371 else 372 { 373 final long resetpoint=(long) mp.getTime()-loopLength/2; 374 TimerTask ani=new TimerTask() { 375 376 @Override 377 public void run() { 378 mp.setTime(resetpoint); 379 } 380 }; 381 t= new Timer(); 382 t.schedule(ani,loopLength/2,loopLength); //first run a half looptime till reset 383 looping=true; 384 } 385 386 } 387 388 protected void mute() { 389 mp.mute(); 390 391 } 392 393 public void forward() { 394 mp.setTime((long) (mp.getTime()+jumpLength)); 395 } 396 397 public void backward() { 398 mp.setTime((long) (mp.getTime()-jumpLength)); 399 400 } 401 402 public void removeVideo() { 403 if (mp.isPlaying()) mp.stop(); 404 mp.release(); 405 406 } 407 408 public void toggleSubs() 409 { 410 //vlc manages it's subtitles in a own list so we have to cycle trough 411 int spu = mp.getSpu(); 412 412 if(spu > -1) { 413 413 spu++; … … 420 420 } 421 421 mp.setSpu(spu); 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 422 } 423 424 public static void addObserver(PlayerObserver observer) { 425 426 observers.add(observer); 427 428 } 429 430 431 432 public static void removeObserver(PlayerObserver observer) { 433 434 observers.remove(observer); 435 436 } 437 438 private static void notifyObservers(long newTime) { 439 440 for (PlayerObserver o : observers) { 441 o.playing(newTime); 442 } 443 444 } 445 446 public String getNativePlayerInfos() { 447 return "VLC "+LibVlc.INSTANCE.libvlc_get_version(); 448 } 449 450 public void faster() { 451 speed.setValue(speed.getValue()+100); 452 453 } 454 455 public void slower() { 456 speed.setValue(speed.getValue()-100); 457 458 } 459 460 public void pause() { 461 if (mp.isPlaying()) mp.pause(); 462 463 } 464 465 public boolean playing() { 466 return mp.isPlaying(); 467 } 468 469 public void error(MediaPlayer arg0) { 470 // TODO Auto-generated method stub 471 472 } 473 474 public void mediaChanged(MediaPlayer arg0) { 475 // TODO Auto-generated method stub 476 477 } 478 479 public boolean hasSubtitles() { 480 if (mp.getSpuCount()==0) return false; else return true; 481 } 482 483 484 484 485 485 } -
applications/editors/josm/plugins/videomapping/src/org/openstreetmap/josm/plugins/videomapping/video/Syncer.java
r21656 r23193 17 17 public void run() { 18 18 SwingUtilities.invokeLater(new Runnable() { 19 19 //here we update 20 20 public void run() { 21 if (pl.isPlaying())pl.updateTime(); //if the video is seeking we get a mess21 if (pl.isPlaying()) pl.updateTime(); //if the video is seeking we get a mess 22 22 } 23 23 }); -
applications/editors/josm/plugins/videomapping/test/videotest.java
r22690 r23193 21 21 public class videotest { 22 22 23 24 25 26 27 28 29 30 31 32 33 34 35 sVP.jump(610000); 36 37 38 39 40 23 /** 24 * @param args 25 */ 26 public static void main(String[] args) { 27 final SimpleVideoPlayer sVP = new SimpleVideoPlayer(); 28 sVP.setFile(new File("C:\\TEMP\\122_0159.MOV")); 29 //sVP.play(); //FIXME We have a bug so we get out of sync if we jump before the video is up (and this we CAN'T DETECT!!!) 30 /* 31 JButton b = new JButton("jump"); 32 b.addActionListener(new ActionListener() { 33 34 public void actionPerformed(ActionEvent e) { 35 sVP.jump(610000); 36 } 37 }); 38 sVP.add(b); 39 */ 40 } 41 41 42 42 }
Note:
See TracChangeset
for help on using the changeset viewer.